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. QT5使用Webkti

    Qt 5.3 使用原来的QT4.8.4项目时QWebView .QWebFrame等类无法编译通过. 出现原因:QWebView .QWebFrame.QWebPage.QWebInspector等这 ...

  2. C#读取excel 找不到可安装的ISAM

    实在没有办法了 就仔细的查看了 一下数据链接字符串: string strConn = "Provider=Microsoft.Jet.Oledb.4.0;Data Source=" ...

  3. 培训笔记——Linux基本命令

    在介绍命令之前,更重要的要先介绍一下快速输入命令的方法. 如果你能记住一些常用命令,毫无疑问,通过命令的操作方式比通过鼠标的操作方式要快. 但是有一些命令或是命令用到的参数如文件名特别复杂特别长,这时 ...

  4. 用Java实现断点续传的基本思路和代码

    用Java实现断点续传的基本思路和代码   URL url = new URL(http://www.oschina.net/no-exist.zip); HttpURLConnection http ...

  5. DevOps means no Ops!

    DevOps means no Ops! 只单纯地搞网络的话或许你可以搞得非常好,并且获得不错的薪资,不过,5年后~10年后~,那时候随便一个人经过简单的学习就能通过Web界面或者专用的工具就能搞定一 ...

  6. LeetCode:二叉树的前、中、后序遍历

    描述: ------------------------------------------------------- 前序遍历: Given a binary tree, return the pr ...

  7. 每天一个Linux命令(12)more命令

    more命令是一个基于vi编辑器文本过滤器,它以全屏幕的方式按页显示文本文件的内容,支持vi中的关键字定位操作. 该命令一次显示一屏文本,满屏后停下来,并且在屏幕的底部出现一个提示信息,给出至今己显示 ...

  8. mutation与action

    mutation 作用: 更改state的状态 说明: 每个mutation对象都有字符串类型(type)与回调函数,在回调函数内进行状态修改,回调函数的第一个参数为state eg: mutatio ...

  9. phpmyadmin mysqlnd cannot connect to

    mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. Please use an administra ...

  10. 【Linux不需要磁盘碎片整理的真正原因是因为Linux只是一个内核,它没有磁盘可以整理】

    [Linux不需要磁盘碎片整理的真正原因是因为Linux只是一个内核,它没有磁盘可以整理]