Spring笔记之一:依赖注入的方式属性注入和构造函数注入

来源:互联网 发布:mdb数据库 编辑:程序博客网 时间:2024/05/21 14:01

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类)
0 0
原创粉丝点击