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. 还原sqlserver2008 r2 数据库步骤

    1: 有备份文件bak 文件(是在sqlserver2008 r2上备份的) 数据库下载地址(讯雷) ed2k://|file|cn_sql_server_2008_r2_express_with_m ...

  2. Codeforces441C_Valera and Tubes(暴力)

    Valera and Tubes time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  3. 从硬盘设计思想到RAID改良之道

    监控硬盘的前生今世关于桌面硬盘.企业级近线硬盘(NL-SAS/SATA)和监控硬盘的差别,我们在前文中已经讲得很详细,这里再换一个角度来看看. "监控硬盘是希捷和西数为视频监控定制的,典型的 ...

  4. QT里面的delay使用

    void delay() { QTime dieTime= QTime::currentTime().addSecs(1); while( QTime::currentTime() < dieT ...

  5. Navicat Premium试用期破解方法(转)

    转载网址https://blog.csdn.net/Jason_Julie/article/details/82864187 1.按步骤安装Navicat Premium,如果没有可以去官网下载:ht ...

  6. web开发工具网站

    配色 http://peise.net/tools/web/   http://retinaicon.com/   http://flattyshadow.com/     免费图片网站 https: ...

  7. python3 内置常用函数系列一

    python3 内置了一系列的常用函数, python英文官方文档详细说明:点击查看, 为了方便查看,将内置常用的函数的记录一下来. Python3版本所有的内置函数: 1.abs() print(a ...

  8. hd acm2035

    求A^B的最后三位数表示的整数.说明:A^B的含义是“A的B次方” 思路:后三位只跟后三位相乘有关,所以可以每乘一次都对1000取余. 代码: #include <stdio.h>#inc ...

  9. hbase shell-general(常规指令)

    hbase shell常规指令解释篇 1. status (显示集群状态,master,server情况,显示内容的详略程度可选) hbase(main)::> help 'status' Sh ...

  10. shell 脚本后台运行知识

    1. bash while01.py &      把脚本放在后台执行 2. ctl + c   停止执行前台执行中的脚本(不能停止在后台运行中的脚本) 3. ctl + z   暂停执行前台 ...