Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

原文地址:http://blog.csdn.net/wangyang1354/article/details/50757098


我们经常会遇到这样一种情景,就是在我们开发项目的时候经常会在一个类中调用其他的类中的方法,来完成我们期望的任务,大部分的情况下往往会采用在当前需要的这个类里面new一个实例出来,然后调用他的方法,那么这样的话会有个问题,就是有一天我想改变下这个类,改为其他的名称,那么这时候必须要做的是同时去调用方的类文件中改变这个改变的类的名称。这样的情况是因为代码的耦合带来了后期维护成本的增加,那么spring的出现就可以很好的起到解耦的作用,而他的核心机制就是依赖注入。

依赖注入与控制反转


依赖注入:对于spring而言,将自己置身于spring的立场上去看,当调用方需要某一个类的时候我就为你提供这个类的实例,就是说spring负责将被依赖的这个对象赋值给调用方,那么就相当于我为调用方注入了这样的一个实例。从这方面来看是依赖注入。


控制反转:对于调用方来说,通常情况下是我主动的去创建的,也就是对于这个对象而言我是控制方,我有他产生与否的权力,但是,现在变了,现在变为spring来创建对象的实例,而我被动的接受,从这一点上看,是控制反转。


这两者的意思是一致的,就看你从谁的角度去看这个问题。不同的角度那么看到的问题可能是不一样的。



依赖注入两种方式


1.设值注入


设值注入:通过set的方式注入值.Ioc容器通过成员变量的setter方法来注入被依赖的对象,这种注入方式简单,直观,因而在spring中大量的使用。

下面我们采用实际的例子来体会一下:

假设这样的一个场景,我想打印消息,这样一件事情

首先定义一个MessageService的接口。

[java] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. package com.siti.spring20160227;  
  2.   
  3. public interface MessageService {  
  4.   
  5.     /** 
  6.      * 消息打印 
  7.      */  
  8.     public void printMessage();  
  9. }  



然后实现这个接口,并实现这个方法。

[java] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. package com.siti.spring20160227;  
  2.   
  3. public class MessagePrinter implements MessageService {  
  4.   
  5.     @Override  
  6.     public void printMessage() {  
  7.         System.out.println(“输出消息!”);  
  8.     }  
  9.   
  10. }  



那么对于我而言,我也定义一个person的接口

[java] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. package com.siti.spring20160227;  
  2.   
  3. public interface Person {  
  4.   
  5.     /** 
  6.      * 人发送消息 
  7.      */  
  8.     public void sendMessage();  
  9. }  

我来实现人这个接口

[java] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. package com.siti.spring20160227;  
  2.   
  3. public class WangYang implements Person{  
  4.   
  5.     private MessageService service;  
  6.       
  7.     public void setService(MessageService service) {  
  8.         this.service = service;  
  9.     }  
  10.   
  11.     @Override  
  12.     public void sendMessage() {  
  13.         this.service.printMessage();  
  14.     }  
  15.   
  16. }  

Spring的配置文件:

[java] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. <?xml version=“1.0” encoding=“UTF-8”?>  
  2. <beans xmlns=“http://www.springframework.org/schema/beans”  
  3.        xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”  
  4.        xsi:schemaLocation=”  
  5. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”>  
  6.   
  7. <!– bean definitions here –>  
  8.     <bean id = “messageService” class = “com.siti.spring20160227.MessagePrinter”></bean>  
  9.     <bean id = “wy” class = “com.siti.spring20160227.WangYang”>  
  10.         <property name=“service” ref=“messageService”></property>  
  11.     </bean>  
  12. </beans>  



测试类如下:

[java] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. package com.siti.spring20160227;  
  2.   
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5.   
  6. public class MainTest {  
  7.   
  8.     public static void main(String[] args) {  
  9.         ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);  
  10.         Person person = context.getBean(“wy”, Person.class);  
  11.         person.sendMessage();  
  12.     }  
  13. }  


2.构造注入


通过构造函数的方式注入。spring以反射的方式执行带指定参数的构造器,当执行带参数的构造器时就可以通过构造器的参数赋值给成员变量,完成构造注入。


那么现在需求变了,我需要改一些东西,下面可以注意下我主要改动了哪里:

在WangYang这个类中添加有参数和无参数的构造函数:

[java] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. package com.siti.spring20160227;  
  2.   
  3. public class WangYang implements Person{  
  4.   
  5.     private MessageService service;  
  6.       
  7.     <span style=“color:#33ff33;”>public WangYang() {  
  8.         super();  
  9.     }  
  10.       
  11.     public WangYang(MessageService service) {  
  12.         this.service = service;  
  13.     }  
  14.   
  15.     </span>public void setService(MessageService service) {  
  16.         this.service = service;  
  17.     }  
  18.   
  19.     @Override  
  20.     public void sendMessage() {  
  21.         this.service.printMessage();  
  22.     }  
  23.   
  24. }  



在Spring配置文件中,稍微改动,即将原来的设值注入换为构造注入即可。

[java] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. <?xml version=“1.0” encoding=“UTF-8”?>  
  2. <beans xmlns=“http://www.springframework.org/schema/beans”  
  3.        xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”  
  4.        xsi:schemaLocation=”  
  5. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”>  
  6.   
  7. <!– bean definitions here –>  
  8.     <bean id = “messageService” class = “com.siti.spring20160227.MessagePrinter”></bean>  
  9.     <bean id = “wy” class = “com.siti.spring20160227.WangYang”>  
  10.         <!– <property name=“service” ref=“messageService”></property> –>  
  11.         <span style=“color:#33ff33;”><constructor-arg ref=“messageService”></constructor-arg></span>  
  12.     </bean>  
  13. </beans>  


这样再次运行MainTest类,程序正常运行。所以从这里也可以体会到,spring这种解耦的方便性和重要性。



设值注入和构造注入的对比


这两种方式,效果是一样的,注入的时机不同,设值注入是先调用无参的构造函数,创建出实例后然后调用set方法注入属性值。而构造输入是通过在调用构造函数初始化实例的同时完成了注入。


设值注入的优点


1. 通过set的方式设定依赖关系显得更加直观,自然,和javabean写法类似。

2. 复杂的依赖关系,采用构造注入会造成构造器过于臃肿,spring 实例化的时候同时实例化其依赖的全部实例,导致性能下降,set方式可以避免这些问题。

3. 在成员变量可选的情况下,构造注入不够灵活。


构造注入的优点


某些特定的情况下,构造注入比设值注入好一些。

1. 构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入,构造注入可以清楚的分清注入的顺序。

2. 组件的调用者无需知道组件内部的依赖关系,符合高内聚原则。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109124.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • web hosting_hotlines

    web hosting_hotlinesBelowyoullfindalistofthe10BestHostsasreviewedbyconsumersandexperiencedwebmasters. Thefollowingwebhostsarerankedbyprice,serverreliability,popularity,softwareusability,di

    2022年10月8日
    1
  • cer证书签名验证[通俗易懂]

    cer证书签名验证[通俗易懂]一个cer证书本身也是需要签名的,这是为了防止cer证书被篡改。证书有两种类型:1.根证书2.根证书签发的子证书。根证书比较特殊,它是自签名的。而其他子证书的签名公钥都保存在它的上级证书里面。可以用C#来做一些验证。首先是根证书的签名验证。//验证根证书签名X509Certificate2x509Root=newX

    2022年6月11日
    79
  • 基于Python的情感分析案例——知网情感词典

    基于Python的情感分析案例——知网情感词典近期老师给我们安排了一个大作业,要求根据情感词典对微博语料进行情感分析。于是在网上狂找资料,看相关书籍,终于搞出了这个任务。现在做做笔记,总结一下本次的任务,同时也给遇到有同样需求的人,提供一点帮助。1、情感分析含义情感分析指的是对新闻报道、商品评论、电影影评等文本信息进行观点提取、主题分析、情感挖掘。情感分析常用于对某一篇新闻报道积极消极分析、淘宝商品评论情感打分、股评情感分析、电影评论情感挖掘。情感分析的内容包括:情感的持有者分析、态度持有者分析、态度类型分析(一系列类型如喜欢(like),讨厌

    2022年8月23日
    7
  • maven打包常用命令总结

    maven打包常用命令总结maven打包常用命令总结基本命令介绍1、mvnclean2、mvncompile3、mvnpackage4、mvninstall5、mvndeploy生产环境打包举例1、生产环境根据源码构建项目:2、可用用到的其他mvn参数介绍:开发过程中常见以下几个命令,这些命令执行后程序究竟发生了什么变化?生产环境如果使用shell脚本配置jenkins构建项目,如何使用命令呢?下面介绍一下我常…

    2022年6月4日
    48
  • git fetch 更新远程代码到本地仓库

    git fetch 更新远程代码到本地仓库

    2021年11月8日
    53
  • 雅虎优化35条

    雅虎优化35条[内容]尽量减少HTTP请求数[服务器]使用CDN(ContentDeliveryNetwork)[服务器]添上Expires或者Cache-ControlHTTP头[服务器]Gzip组件[css]把样式表放在顶部[js]把脚本放在底部[css]避免使用CSS表达式[js,css]把JavaScript和CSS放到外面[内容]减少DNS查找[js,css

    2022年7月13日
    16

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号