• [译]15-spring 自动装配


    前面的章节我们已经学习了如何使用bean元素在xml配置文件中声明一个bean.也学习了如何使用bean的子元素contructor-arg

    和property进行bean的依赖项的注入.

    之前bean的装配(依赖项的注入)都是我们手动进行了.我们之前使用contructor-arg元素指定使用bean的构造器参数进行依赖项

    的注入;使用property元素指定使用bean的setter方法进行依赖项的注入.其实spring IOC容器支持bean的自动装配(依赖项的自

    动注入).使用bean的自动装配功能可以大大缩减配置元数据的大小.

    可以使用bean元素的autowire属性指定自动装配的类型,spring支持如下类型:

    自动装配的类型 描述
    no/default autowire="no"指定spring不使用自动装配,需要手动装配
    byName 按照bean属性的名字从spring容器中找同名的bean进行注入,适用于setter注入
    byType 按照bean属性的类型从spring容器中找相同类型的bean进行注入,适用于setter注入
    constructor 按照类型装配,跟byType类似.适用于构造器参数注入

    下面我们将分别讲解着四种装配类型

    不使用自动装配-no

    我们之前讲解的所有的例子都属于这种类型.在这种情况下所有bean的装配都是手动进行的.我们再用一个例子复习下

    1.新建包com.tutorialspoint.autowire,并在包中新建Cat.java、Dog.java、Duck.java.后面所有例子都会用到这三个类:

    //Cat.java
    package com.tutorialspoint.autowire;
    
    public class Cat {
    
        public void sayHi(){
            System.out.println("miao miao ... ");
        }
    }
    
    //Dog.java
    package com.tutorialspoint.autowire;
    
    public class Dog {
    
        public void sayHi(){
            System.out.println("wang wang ... ");
        }
    }
    
    //Duck.java
    package com.tutorialspoint.autowire;
    
    public class Duck {
    
        public void sayHi(){
            System.out.println("ga ga ... ");
        }
    }

    2.新建包com.tutorialspoint.autowire.no,并在包中新建Zoo.java,内容如下:

    package com.tutorialspoint.autowire.no;
    
    import com.tutorialspoint.autowire.*;
    
    public class Zoo {
    
        private Cat cat;
        private Dog dog;
        private Duck duck;
        
        public void setCat(Cat cat) {
            this.cat = cat;
        }
        public void setDog(Dog dog) {
            this.dog = dog;
        }
        public void setDuck(Duck duck) {
            this.duck = duck;
        }
        
        public void print(){
            
            if(cat==null){
                System.out.println("cat is null");
            }else{
                cat.sayHi();
            }
            
            if(dog==null){
                System.out.println("dog is null");
            }else{
                dog.sayHi();
            }
            
            if(duck==null){
                System.out.println("duck is null");
            }else{
                duck.sayHi();
            }
        }
        
    }

    3.在src目录下新建autowire_no.xml配置文件,内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
        
       <bean id="cat" class="com.tutorialspoint.autowire.Cat"></bean>
       <bean id="dog" class="com.tutorialspoint.autowire.Dog"></bean>
       <bean id="duck" class="com.tutorialspoint.autowire.Duck"></bean>
      
       <bean id="zoo" class="com.tutorialspoint.autowire.no.Zoo">
           <property name="cat" ref="cat"></property>
           <property name="dog" ref="dog"></property>
       </bean>
    
    </beans>

    4.在com.tutorialspoint.autowire.no包中新建MainApp.java.内容如下:

    package com.tutorialspoint.autowire.no;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApp {
    
        public static void main(String[] args) {
            
            ApplicationContext context = new ClassPathXmlApplicationContext("autowire_no.xml");
            
            Zoo zoo = (Zoo) context.getBean("zoo");
            
            zoo.print();
        }
    }

    5.运行程序,检查结果:

    通过上面的程序我们可以得出如下结论:

    手动装配bean,bean的所有依赖项都要在bean元素中明确指定.如果不进行指定spring容器就不会注入该属性.

    按照名字进行自动装配-byName

    在byName装配方式下,spring首先会反射autowire="byName"的bean,得到bean中的所有属性名(根据setter推算),然后从容

    器中寻找同名的bean,最后把找到的bean注入到当前bean中.我们还是用代码说话:

    1.新建包com.tutorialspoint.autowire.byname,并在包中新建Zoo.java类.内容如下:

    package com.tutorialspoint.autowire.byname;
    
    import com.tutorialspoint.autowire.Cat;
    import com.tutorialspoint.autowire.Dog;
    import com.tutorialspoint.autowire.Duck;
    
    public class Zoo {
    
        private Cat cat;
        private Dog dog;
        private Duck duck;
        // 自动装配并不适用于原始类型.这时候我们可以对该属性进行手动装配
        private String zooName;
    
        public void setZooName(String zooName) {
            this.zooName = zooName;
        }
    
        public void setCat(Cat cat) {
            this.cat = cat;
        }
    
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    
        public void setDuck(Duck duck) {
            this.duck = duck;
        }
    
        public void print() {
    
            if (cat == null) {
                System.out.println("cat is null");
            } else {
                cat.sayHi();
            }
    
            if (dog == null) {
                System.out.println("dog is null");
            } else {
                dog.sayHi();
            }
    
            if (duck == null) {
                System.out.println("duck is null");
            } else {
                duck.sayHi();
            }
            
            System.out.println(zooName);
        }
    
    }

    2.在src目录下新建autowire_byName.xml配置文件.内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
        
       <!-- 名为zoo的bean在按照byName进行装配的时候,可以适配名字为cat、dog
            的bean,不能适配名字为duck1的bean。所以最终zoo中会注入进cat和dog
            不会注入duck. -->
       <bean id="cat" class="com.tutorialspoint.autowire.Cat"></bean>
       <bean id="dog" class="com.tutorialspoint.autowire.Dog"></bean>
       <bean id="duck1" class="com.tutorialspoint.autowire.Duck"></bean>
       
       <bean id="zoo" class="com.tutorialspoint.autowire.byname.Zoo" autowire="byName">
           <!-- 由于自动装配仅适用于引用类型,普通类型还需要手动进行注入 -->
           <property name="zooName" value="international_zoo"></property>
       </bean>
    
    </beans>

    3.在包com.tutorialspoint.autowire.byname中新建MainApp.java.内容如下:

    package com.tutorialspoint.autowire.byname;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApp {
    
        public static void main(String[] args) {
            
            ApplicationContext context = new ClassPathXmlApplicationContext("autowire_byName.xml");
            
            Zoo zoo = (Zoo)context.getBean("zoo");
            
            zoo.print();
        }
    }

    4.运行代码,检查结果:

    分析结果可以看到cat和dog已经按照属性名字自动装配到了zoo中.duck1由于没有匹配的属性名所以没有进行装配.zooName是

    我们手动进行注入的。

    按照类型进行自动装配-byType

    在byType装配方式下,spring首先会反射autowire="byType"的bean,得到bean属性的返回类型,然后去spring容器中按照类

    型去匹配,最后把匹配到的bean注入到当前bean中.看个例子就明白了:

    1.新建包com.tutorialspoint.autowire.bytype,并在包中新建Zoo.java类,内容如下:

    package com.tutorialspoint.autowire.bytype;
    
    import com.tutorialspoint.autowire.Cat;
    import com.tutorialspoint.autowire.Dog;
    import com.tutorialspoint.autowire.Duck;
    
    public class Zoo {
    
        private Cat cat;
        private Dog dog;
        private Duck duck;
        // 自动装配并不适用于原始类型.这时候我们可以对该属性进行手动装配
        private String zooName;
    
        public void setZooName(String zooName) {
            this.zooName = zooName;
        }
    
        public void setCat(Cat cat) {
            this.cat = cat;
        }
    
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    
        public void setDuck(Duck duck) {
            this.duck = duck;
        }
    
        public void print() {
    
            if (cat == null) {
                System.out.println("cat is null");
            } else {
                cat.sayHi();
            }
    
            if (dog == null) {
                System.out.println("dog is null");
            } else {
                dog.sayHi();
            }
    
            if (duck == null) {
                System.out.println("duck is null");
            } else {
                duck.sayHi();
            }
    
            System.out.println(zooName);
        }
    
    }

    2.在src目录下新建配置文件autowire_byType.xml。内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
        
       <!-- 名为zoo的bean在按照byType进行装配的时候,可以适配名字为cat1、dog1、duck1
            的bean的类型。所以最终cat1、dog1、duck1会被分别注入进zoo的cat、dog、duck属性。
            在按照类型进行装配的时候,如过有两个bean的类型符合的话,spring就不知道最终该使用哪个,这时候我们
            可以使用primary="true"告诉spring优先使用本bean
       -->
       <bean id="cat1" class="com.tutorialspoint.autowire.Cat" primary="true"></bean>
       <bean id="cat2" class="com.tutorialspoint.autowire.Cat"></bean>
       <bean id="dog1" class="com.tutorialspoint.autowire.Dog"></bean>
       <bean id="duck1" class="com.tutorialspoint.autowire.Duck"></bean>
       
       <bean id="zoo" class="com.tutorialspoint.autowire.bytype.Zoo" autowire="byType">
           <!-- 由于自动装配仅适用于引用类型,普通类型还需要手动进行注入 -->
           <property name="zooName" value="international_zoo"></property>
       </bean>
    
    </beans>

    3.在包com.tutorialspoint.autowire.bytype中新建MainApp.java。内容如下:

    package com.tutorialspoint.autowire.bytype;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApp {
    
        public static void main(String[] args) {
            
            ApplicationContext context = new ClassPathXmlApplicationContext("autowire_byType.xml");
            
            Zoo zoo = (Zoo)context.getBean("zoo");
            
            zoo.print();
        }
    }

    4.运行程序,检查结果:

    构造器参数类型自动装配-constructor

    在constructor自动装配模式下,spring首先会反射bean的构造函数,得出构造函数的参数的类型,然后起spring容器中匹配合适的

    类型的bean,最后使用构造器参数注入的方法把符合的bean注入到当前bean中。看代码:

    1.新建包com.tutorialspoint.autowire.constructor,并在包中新建Zoo.java。内容如下:

    package com.tutorialspoint.autowire.constructor;
    
    import com.tutorialspoint.autowire.*;
    
    public class Zoo {
    
        private Cat cat;
        private Dog dog;
        private Duck duck;
        private String zooName;
        
        public Zoo(Cat cat, Dog dog, Duck duck, String zooName) {
            this.cat = cat;
            this.dog = dog;
            this.duck = duck;
            this.zooName = zooName;
        }
        
        public void print() {
    
            if (cat == null) {
                System.out.println("cat is null");
            } else {
                cat.sayHi();
            }
    
            if (dog == null) {
                System.out.println("dog is null");
            } else {
                dog.sayHi();
            }
    
            if (duck == null) {
                System.out.println("duck is null");
            } else {
                duck.sayHi();
            }
    
            System.out.println(zooName);
        }
    
    }

    2.在src目录下新建autowire_constructor.xml,内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
        
       <!-- constructor跟byType十分相似.
            名为zoo的bean在按照constructor进行装配的时候,可以适配名字为cat1、dog1、duck1
            的bean的类型。所以最终cat1、dog1、duck1会被分别注入进zoo的cat、dog、duck属性(使用
            构造器参数进行注入)。
            在按照constructor进行装配的时候,如过有两个bean的类型符合的话,spring就不知道最终该使用哪个,这时候我们
            可以使用primary="true"告诉spring优先使用本bean
       -->
       <bean id="cat1" class="com.tutorialspoint.autowire.Cat" primary="true"></bean>
       <bean id="cat2" class="com.tutorialspoint.autowire.Cat"></bean>
       <bean id="dog" class="com.tutorialspoint.autowire.Dog"></bean>
       <bean id="duck1" class="com.tutorialspoint.autowire.Duck"></bean>
       
       <bean id="zoo" class="com.tutorialspoint.autowire.constructor.Zoo" autowire="constructor">
           <!-- 由于自动装配仅适用于引用类型,普通类型还需要手动进行注入 -->
           <constructor-arg name="zooName" value="international_zoo"></constructor-arg>
       </bean>
    
    </beans>

    3.在com.tutorialspoint.autowire.constructor包中新建MainApp.java。内容如下:

    package com.tutorialspoint.autowire.constructor;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApp {
    
        public static void main(String[] args) {
            
            ApplicationContext context = new ClassPathXmlApplicationContext("autowire_constructor.xml");
            
            Zoo zoo = (Zoo)context.getBean("zoo");
            
            zoo.print();
        }
    }

    4.运行程序,检查结果:

    如果使用sping的自动装配,本人不推荐使用xml的配置方式.最好使用注解的配置方式。原因如下:

    1.基于xml的自动装配粒度态度。默认会装配所有符合条件的bean.不能指定哪个属性不进行自动装配

    2.不能指定哪些属性必须进行装配,否则抛出异常.

    以上两点使用spring的注解配置元数据都是可以做到的。我们下节就讲解spring注解配置元数据。

  • 相关阅读:
    题解【洛谷P2221】[HAOI2012]高速公路
    APIO2020 滚粗记
    2018 百度之星程序设计大赛
    TimusOJ2058. 100500 palidnromes 最小回文划分模板
    HDU-5937 Equation dfs+剪枝
    Codeforces 932G
    CodeChef Palindromeness 回文自动机
    HDU-5421 Victor and String 回文自动机
    P4287 [SHOI2011]双倍回文 回文自动机
    2020CCPC绵阳/gym102822 C. Code a Trie 贪心
  • 原文地址:https://www.cnblogs.com/sysman/p/4485199.html
Copyright © 2020-2023  润新知