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. activiti--5 -----------------Activiti 工作流 流程各个步骤所涉及到的表

    ACT_RE_*: 'RE'表示repository. 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等). ACT_RU_*: 'RU'表示runtime. 这些运行时的表,包含流程实例 ...

  2. Python中PIL及Opencv转化

    转载:http://blog.sina.com.cn/s/blog_80ce3a550102w26x.html Convert between Python tuple and list a = (1 ...

  3. R语言数据管理(二):模式与类

      最常用的4种数据类型是数值型(numeric).字符型(character)(字符串).日期型(Date)或POSIXct(基于日期的).逻辑型(logical)(TRUE或FALSE). 变量中 ...

  4. sql把字符数组转换成表

    需求:把字符串1,2,3变成表里的行数据 方法:用自定义函数实现 /* 获取字符串数组的 Table */ from sysobjects where id = object_id('Get_StrA ...

  5. Python OOP(2)-static method,class method and instance method

    静态方法(Static Method): 一种简单函数,符合以下要求: 1.嵌套在类中. 2.没有self参数. 特点: 1.类调用.实例调用,静态方法都不会接受自动的self参数. 2.会记录所有实 ...

  6. golang 获取指定目录下的子文件列表

    GO语言按照深度遍历文件 原创 2016年07月20日 09:45:19 标签: go语言 / 遍历 / string 1971 常规方法不使用pathfilepath包 go的filepath包 g ...

  7. RSA加密方法java工具类

    package com.qianmi.weidian.common.util; import java.io.ByteArrayOutputStream; import java.security.K ...

  8. Oracle数据库定义语言(DDL)

    --使用Create遇见创建表 Create Table table_name ( column_name datatype [null|not null], column_name datatype ...

  9. AJAX+json+jquery实现预加载瀑布流布局

    宽度是一定的高度不定的瀑布流布局 也可以说是无缝拼图 当浏览器滚动到底部时候自动加载图片 加载的图片地址用json 在img.js里 ,还有正在加载动画是用 css3制作的 在ff等支持css3可以显 ...

  10. php设计模式课程---1、什么是设计模式

    php设计模式课程---1.什么是设计模式 一.总结 一句话总结:经典场景的经典解决方法. 经典场景的经典解决方法 1.设计模式使用的通俗场景有哪些? 比如:拍电影时,常用设计模式 感情狗血剧:误会模 ...