zoukankan      html  css  js  c++  java
  • Spring 学习笔记(五)—— Bean之间的关系、作用域、自动装配

    继承

      Spring提供了配置信息的继承机制,可以通过为<bean>元素指定parent值重用已有的<bean>元素的配置信息。

    <?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.xsd">
            <bean id="baseuser" class="Demo05.BaseUser">
                <property name="userid" value="1"/>
                <property name="username" value="rekent"/>
                <property name="password" value="123"/>
            </bean>
        
            <bean id="user1" parent="baseuser">
                <property name="userid" value="2"/>
            </bean>
    </beans>

      例如:上述我创建了一个BaseUser,其后的只要继承了BaseUser的Bean都会有BaseUser的配置信息,此时只需要重写不同的部分即可。

      注意:这里的继承是指配置信息的重用,与面向对象的继承毫无关系。另外,Spring并没有要求配置信息存在继承关系的两个Bean是统一类型的,只要具有相关属性即可。


    依赖

      Spring 通过Bean之间的引用ref建立了所有Bean之间的完整依赖关系,当实例化一个Bean时,IoC容器能保证该Bean所依赖的其他Bean已经初始化完毕。

      但是有时,可能要求Bean A的初始化必须在Bean B的初始化之后,而B不是A的属性,因此无法通过向A注入B来保证首先完成B的创建。

      此时便提供了depends-on属性来指定前置依赖的Bean。例如:

    <bean id="father" class=""></bean>
    <bean id="son" class="" depends-on="father"></bean>

    作用域

      作用域通过<bean>元素的scope属性指定,Spring支持5种作用域。

    作用域 描述
    singleton 一个Bean定义对应唯一一个对象实例,Bean以单实例的方式存在(默认)
    prototype 一个Bean定义对应多个对象实例,每次调用getBean()时,就创建一个新实例(开销大,不推荐)
    request (仅在基于Web的SpringApplicationContext情形下有效)在一次Http请求中,一个Bean定义对应一个实例,即每个请求都会有各自的Bean。
    session (仅在基于Web的SpringApplicationContext情形下有效)在一个HtppSession中,一个Bean定义对应一个实例。
    global session (仅在基于Web的SpringApplicationContext情形下有效)在一个全局的Http Session中,一个Bean定义对应一个实例。

    自动装配(源于他人,原文链接:http://www.cnblogs.com/sysman/p/4485199.html

    可以使用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注解配置元数据。

  • 相关阅读:
    jquery animate()方法 语法
    jquery unload方法 语法
    jquery undelegate()方法 语法
    jquery unbind()方法 语法
    jquery trigger() 方法 语法
    jquery toggle()方法 语法
    jquery change() 函数 语法
    jquery blur()函数 语法
    jquery bind()方法 语法
    jquery checked选择器 语法
  • 原文地址:https://www.cnblogs.com/rekent/p/7212653.html
Copyright © 2011-2022 走看看