理解依赖注入:参考https://blog.csdn.net/taijianyu/article/details/2338311
一、依赖注入让bean与bean之间以配置文件组织在一起,而不是以硬编码的方式耦合在一起。
二、依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。
三、不管是依赖注入,还是控制反转,都说明Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现互相透明。在理解依赖注入之前,看如下这个问题在各种社会形态里如何解决:一个人(Java实例,调用者)需要一把斧子(Java实例,被调用者)。
(1)原始社会里,几乎没有社会分工。需要斧子的人(调用者)只能自己去磨一把斧子(被调用者)。对应的情形为:Java程序里的调用者自己创建被调用者。
(2)进入工业社会,工厂出现。斧子不再由普通人完成,而在工厂里被生产出来,此时需要斧子的人(调用者)找到工厂,购买斧子,无须关心斧子的制造过程。对应Java程序的简单工厂的设计模式。
(3)进入“按需分配”社会,需要斧子的人不需要找到工厂,坐在家里发出一个简单指令:需要斧子。斧子就自然出现在他面前。对应Spring的依赖注入。
第一种情况下,Java实例的调用者创建被调用的Java实例,必然要求被调用的Java类出现在调用者的代码里。无法实现二者之间的松耦合。
第二种情况下,调用者无须关心被调用者具体实现过程,只需要找到符合某种标准(接口)的实例,即可使用。此时调用的代码面向接口编程,可以让调用者和被调用者解耦,这也是工厂模式大量使用的原因。但调用者需要自己定位工厂,调用者与特定工厂耦合在一起。
第三种情况下,调用者无须自己定位工厂,程序运行到需要被调用者时,系统自动提供被调用者实例。事实上,调用者和被调用者都处于Spring的管理下,二者之间的依赖关系由Spring提供。
所谓依赖注入,是指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。Spring的依赖注入对调用者和被调用者几乎没有任何要求,完全支持对POJO之间依赖关系的管理。依赖注入通常有两种:
·设值注入。
·构造注入。
<!--spring中的依赖注入 依赖注入: Dependency Injection IOC的作用: 降低程序间的耦合(依赖关系) 依赖关系的管理: 以后都交给spring来维护 在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明 依赖关系的维护: 就称之为依赖注入 依赖注入: 能注入的数据:有三种 基本类型和String 其他bean类型(在配置文件中或者注解配置过的bean) 复杂类型/集合类型 注入的方式:有三种 第一种:使用构造函数提供 第二种:使用set方法提供 第三种:使用注解提供 -->
构造函数注入:
<!--构造函数注入: 使用的标签:constructor-age 标签出现的位置:bean标签的内部 标签中的属性 type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型 index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置从0开始 name:用于给构造函数中指定名称的参数赋值(常用的) ===================以上三个用于给构造函数中哪个参数赋值===================== value:用于给基本类型和String类型的数据 ref:用于指定其他的bean类型数据。它指的就是在spring的IOC核心容器中出现过的bean对象 优势: 在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功 弊端: 改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。 --> <bean id="accountService" class="cn.flypig666.service.impl.AccountServiceImpl"> <constructor-arg name="name" value="飞猪"></constructor-arg> <constructor-arg name="age" value="20"></constructor-arg> <constructor-arg name="birthday" ref="now"></constructor-arg> </bean> <!--配置一个日期对象--> <bean id="now" class="java.util.Date"></bean>
public class AccountServiceImpl implements IAccountService { //如果是经常变化的数据,并不适用于注入的方式 private String name; private Integer age; private Date birthday; public AccountServiceImpl(String name,Integer age,Date birthday){ this.name = name; this.age = age; this .birthday = birthday; } public void saveAccount(){ System.out.println("service中的saveAccount方法执行....."+name+","+age+","+birthday); } }
set方法注入:
1 <!--set方法注入 更常用的方式 2 涉及的标签:property 3 出现的位置:bean标签的内部 4 标签的属性 5 name:用于指定注入时所调用的set方法名称 6 value:用于给基本类型和String类型的数据 7 ref:用于指定其他的bean类型数据。它指的就是在spring的IOC核心容器中出现过的bean对象 8 优势: 9 创建对象时没有明确的限制,可以直接使用默认构造函数 10 弊端: 11 如果有某个成员必须有值,则获取对象时有可能set方法没有执行 12 --> 13 <bean id="accountService2" class="cn.flypig666.service.impl.AccountServiceImpl2"> 14 <property name="name" value="test"></property> 15 <property name="age" value="20"></property> 16 <property name="birthday" ref="now"></property> 17 </bean>
复杂类型的注入/集合类型的注入:
1 <!--复杂类型的注入/集合类型的注入 2 用于给List结构集合注入的标签 3 list array set 4 用于给map结构集合注入的标签: 5 map props 6 结构相同,标签可以交换 7 --> 8 <bean id="accountService3" class="cn.flypig666.service.impl.AccountServiceImpl3"> 9 <property name="mystrs"> 10 <array> 11 <value>AAA</value> 12 <value>bbb</value> 13 <value>DDD</value> 14 </array> 15 </property> 16 <property name="myList"> 17 <list> 18 <value>AAA</value> 19 <value>bbb</value> 20 <value>DDD</value> 21 </list> 22 </property> 23 <property name="mySet"> 24 <set> 25 <value>AAA</value> 26 <value>bbb</value> 27 <value>DDD</value> 28 </set> 29 </property> 30 <property name="myMap"> 31 <map> 32 <entry key="testA" value="aaa"></entry> 33 <entry key="testB" > 34 <value>BBB</value> 35 </entry> 36 </map> 37 </property> 38 <property name="myProps"> 39 <props> 40 <prop key="testA">adsfsaf</prop> 41 <prop key="testB">bbbggg</prop> 42 </props> 43 </property> 44 45 </bean>