1、在传统的程序设计中,调用亲自创建被调用者的实例,即由程序控制“对象之间的依赖关系”,这种方式的耦合度比较高;控制反转就是将由程序控制的“对象间的依赖关系”转交给Ioc容器来进行控制,被调用者的实例创建工作不再是调用者完成, 大大降低了调用者和被调用者之间的关系。Ioc(inversion of control:控制反转)和Di(dependency Injection:依赖注入) 是相同的概念。

  

2、实现依赖注入的方式:
2.1、属性注入:
//bean类 被关联
package com.liu.spring;
public class RefBean {
private String meg;
public String getMeg() {
return meg;
}
public void setMeg(String meg) {
this.meg = meg;
}
}
//bean 将关联RefBean类
package com.liu.spring;
public class MessageBean {
private String message;
private RefBean refBean;//关联的RefBean类
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public RefBean getRefBean() {
return refBean;
}
public void setRefBean(RefBean refBean) {
this.refBean = refBean;
}
}
//配置文件
<beans>
<!-- 配置文件 1.先配置类为RefBean -->
<bean id="refBean" class="com.liu.spring.RefBean">
<property name="meg">
<value>我是属性注入方式实现的(我在RefBean类中)</value>
</property>
</bean>
<!-- 2、再来配置类 MessageBean -->
<bean id="messageBean" class="com.liu.spring.MessageBean">
<property name="message">
<value>Spring框架(我是在MessageBean类中)</value>
</property>
<!-- 加入另一个bean -->
<property name="refBean">
<ref local="refBean"/>
</property>
</bean>
</beans>
//测试类
package com.liu.action;
public class Action_01 {
public static void main(String[] args) {
//加载配置文件
ClassPathResource resource=new ClassPathResource("applicationContext.xml");
//创建bean工厂
BeanFactory factory=new XmlBeanFactory(resource);
//获取对用的实例(就避免的new对象)
MessageBean message=(MessageBean) factory.getBean("messageBean");
//打印结果
System.out.println(message.getMessage()+","+message.getRefBean().getMeg());
}
}
//最终的结果是
Spring框架(我是在MessageBean类中),我是属性注入方式实现的(我在RefBean类中)

  

2.2、构造方法注入:
注:只需在被关联的类中写好构造函数,在配置文件之中写好配置文件就行
//配置文件写法
<bean id="messageBean" class="com.liu.spring.MessageBean">
<!--- 构造函数注入的关键标签 --->
<constructor-arg index="0">
<value>Spring框架(我是在MessageBean类中)</value>
</constructor-arg>
<constructor-arg index="1">
<!-- 引用之外的bean -->
<ref local="refBean"/>
</constructor-arg>
</bean>
<!-- 被关联的bean类--->
<bean id="refBean" class="com.liu.spring.RefBean">
<property name="meg">
<value>我是属性注入方式实现的(我在RefBean类中)</value>
</property>
</bean>
2.3、构造注入须知:
为了避免现在的配置文件的歧义而引起的张冠李戴,在bean中存在多个构造函数时,使用显示指定index和type属性
比较直观。
2.4、属性注入和构造注入的比较:
2.4.1、属性注入的特点是不需要知道属性的类型,但是必须知道属性的名称;使用set()方法实现依赖注入
2.4.2、构造函数注入的特点是不需要知道参数的名称,不需要知道set(),但是必须知道参数的序号和类型,必须定义包含不同参数
的构造函数。
2.4.3、构造函数注入和属性注入方式各有优缺点。
3、循环依赖问题:
3.1、什么是循环依赖:
spring容器能够顺利实例化以构造函数注入的方式配置的Bean有一个前提:Bean引用的构造函数入参引用的对象必须已近准备就绪。由于这种机制,如果两个bean都采用构造函数注入,而且都是通过构造函数入参引用对方,就会发生死锁,就是依赖循环。 实体类如下:
//Boss类
package com.liu.spring;
public class Boss {
private String name;
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
//构造函数
public Boss(String name, Car car) {
super();
this.name = name;
this.car = car;
}
}
//car类
package com.liu.spring;
public class Car {
private String brand;
private Boss boss;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Boss getBoss() {
return boss;
}
public void setBoss(Boss boss) {
this.boss = boss;
}
//构造函数
public Car(String brand, Boss boss) {
super();
this.brand = brand;
this.boss = boss;
}
}
//配置文件
<!-- 循环依赖问题的配置文件如下 (错) -->
<bean id="car" class="com.liu.spring.Car"><!-- car类 -->
<constructor-arg>
<value>我是劳斯莱斯(来之car类)</value>
</constructor-arg>
<constructor-arg>
<ref local="boss"/><!-- 引用boss -->
</constructor-arg>
</bean>
<bean id="boss" class="com.liu.spring.Boss">
<constructor-arg>
<value>我是刘明(来之boss类)</value>
</constructor-arg>
<constructor-arg>
<ref local="car"/><!-- 引用car -->
</constructor-arg>
</bean>
异常为:Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
3.2、循环依赖解决方法(配置文件使用属性注入)
<!-- 循环依赖问题的配置文件如下 (正确) -->
<bean id="car" class="com.liu.spring.Car">
<property name="brand">
<value>我是劳斯拉斯(来之car类)</value>
</property>
<property name="boss">
<ref local="boss"/>
</property>
</bean>
<bean id="boss" class="com.liu.spring.Boss">
<property name="name">
<value>我是不知道(来之boss类)</value>
</property>
<property name="car">
<ref local="car"/>
</property>
</bean>
------测试类------------------
//加载配置文件
ClassPathResource resource=new ClassPathResource("applicationContext.xml");
//创建bean工厂
BeanFactory factory=new XmlBeanFactory(resource);
//获得对应的实体类
Car car=(Car) factory.getBean("car");
Boss boss=(Boss) factory.getBean("boss");
System.out.println(car.getBrand()+"========"+car.getBoss().getName());
System.out.println(boss.getName()+"======="+boss.getCar().getBrand());
最后的结果是:
我是劳斯拉斯(来之car类)========我是不知道(来之boss类)
我是不知道(来之boss类)=======我是劳斯拉斯(来之car类)

  

spring--设置注入VS构造注入的更多相关文章

  1. Spring注入值得2种方式:属性注入和构造注入

    Spring是一个依赖注入(控制反转)的框架,那么依赖注入(标控制反转)表现在那些地方了? 即:一个类中的属性(其他对象)不再需要手动new或者通过工厂方法进行创建,而是Spring容器在属性被使用的 ...

  2. Spring接口编程_设值注入和构造注入

    说明: UserManagerImp是设值注入,UserManagerImp2是构造注入 接口不注入,也就是在Spring配置文件中没有接口的<bean>,但是定义的时候是用接口 priv ...

  3. 【Spring学习笔记-2.1】Spring的设值注入和构造注入

    设值注入: 先通过无参数的构造函数创建一个Bean实例,然后调用对应的setter方法注入依赖关系: 配置文件: <?xml version="1.0" encoding=& ...

  4. 【Spring实战】—— 2 构造注入

    本文讲解了构造注入以及spring的基本使用方式,通过一个杂技演员的例子,讲述了依赖注入属性或者对象的使用方法. 如果想要使用spring来实现依赖注入,需要几个重要的步骤: 1 定义主要的类和需要分 ...

  5. Spring学习(3)---Spring设值注入和构造注入

    (一)设值注入就是指要被注入的类中定义有一个setter()方法,并在参数中定义需要注入的对象.简单的看个例子. 建一个User类: package com.ioc; public class Use ...

  6. SSM-Spring-04:Spring的DI的构造注入,P命名注入,和集合注入

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- DI和IOC相比,DI更偏向于实现 DI的set方式注入在前面入门案例里有写,所以此处不多啰嗦,直接开搞,先说 ...

  7. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring DI(依赖注入)的实现方式属性注入和构造注入

    依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念. 当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的 ...

  8. spring中用xml配置构造注入的心得

    spring中用xml配置构造注入时,如果 <constructor-arg> 属性都是 ref ,则不用理会参数顺序 <constructor-arg ref="kill ...

  9. 7.28.1 Spring构造注入还是设置注入

    1. 构造方法注入代码如下:public UserManagerImpl(UserDao userDao) {                                              ...

随机推荐

  1. [ACM] FZU 2087 统计数边 (有多少边至少存在一个最小生成树里面)

    Problem Description 在图论中,树:随意两个顶点间有且仅仅有一条路径的图. 生成树:包括了图中全部顶点的一种树. 最小生成树:对于连通的带权图(连通网)G,其生成树也是带权的. 生成 ...

  2. CentOS7.x 报错 There are no enabled repos.

    地址 :http://mirrors.163.com/centos/7/os/x86_64/Packages/   wget http://mirrors.163.com/centos/7/os/x8 ...

  3. jQuery实现复选框全选/所有取消/反选/获得选择的值

    <!DOCTYPE html> <html> <head> <script type="text/javascript" src=&quo ...

  4. 错误解决Error configuring application listener of class org.springframework.web.util.Log4jConfigListener(转发)

    Spring MVC-----maven项目导入后启动tomcat出现如下错误 参考:http://blog.csdn.net/itlionwoo/article/details/17523371 解 ...

  5. 【leetcode刷题笔记】Substring with Concatenation of All Words

    You are given a string, S, and a list of words, L, that are all of the same length. Find all startin ...

  6. 【三】MongoDB文档的CURD操作

    一.插入文档 使用insert方法插入文档到一个集合中,如果集合不存在创建集合,有以下几种方法: db.collection.insertOne({}):(v3.2 new)  #插入一个文档到集合中 ...

  7. 【DP】最长不下降子序列问题(二分)

    Description 给你一个长度为n的整数序列,按从左往右的顺序选择尽量多的数字并且满足这些数字不下降. Thinking 朴素dp算法:F[i]表示到第i位为止的最长不下降子序列长度 F[i]= ...

  8. POJ 1183 反正切函数的应用

    H - 反正切函数的应用 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit ...

  9. codevs 1299 切水果 线段树

    1299 切水果  时间限制: 1 s  空间限制: 128000 KB     题目描述 Description 简单的说,一共N个水果排成一排,切M次,每次切[L,R]区间的所有水果(可能有的水果 ...

  10. vs2017调用目标发生了异常

    解决办法: 1. 在开始菜单,找到“Visual Studio Tools”文件夹中的“VS 2017的开发人员命令提示符 ” 运行. 2. 输入:devenv /Safemode 3. 会以安全模式 ...