spring--设置注入VS构造注入

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类)

  

posted @ 2017-01-18 08:20  ATJAVA  阅读(573)  评论(0编辑  收藏  举报