一、在传统的程序设计中,调用亲自建立被调用者的实例,即由程序控制“对象之间的依赖关系”,这种方式的耦合度比较高;控制反转就是将由程序控制的“对象间的依赖关系”转交给Ioc容器来进行控制,被调用者的实例建立工做再也不是调用者完成, 大大下降了调用者和被调用者之间的关系。Ioc(inversion of control:控制反转)和Di(dependency Injection:依赖注入) 是相同的概念。
二、实现依赖注入的方式: 2.一、属性注入: //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> <!-- 二、再来配置类 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.二、构造方法注入: 注:只需在被关联的类中写好构造函数,在配置文件之中写好配置文件就行 //配置文件写法 <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.三、构造注入须知: 为了不如今的配置文件的歧义而引发的张冠李戴,在bean中存在多个构造函数时,使用显示指定index和type属性 比较直观。 2.四、属性注入和构造注入的比较: 2.4.一、属性注入的特色是不须要知道属性的类型,可是必须知道属性的名称;使用set()方法实现依赖注入 2.4.二、构造函数注入的特色是不须要知道参数的名称,不须要知道set(),可是必须知道参数的序号和类型,必须定义包含不一样参数 的构造函数。 2.4.三、构造函数注入和属性注入方式各有优缺点。 三、循环依赖问题: 3.一、什么是循环依赖: 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.二、循环依赖解决方法(配置文件使用属性注入) <!-- 循环依赖问题的配置文件以下 (正确) --> <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类)