zoukankan      html  css  js  c++  java
  • spring-第五篇之spring容器中的bean

    1、bean的基本定义和bean别名

    2、容器中bean的作用域

          singleton:单例模式,在整个spring IoC容器中,singleton作用域的bean将只生成一个实例。

          prototype:每次通过容器的getBean()方法获取prototype作用域的bean时,都将产生一个新的bean实例。

          request:对于一次HTTP请求,request作用域的bean将只生成一个实例,这意味着,在同一次HTTP请求内,程序每次请求该bean,得到的总是同一个实例。只有在Web应用中使用spring时,该作用域才真正的有效。

          session:对于一次HTTP会话,sesion作用域的bean将只生成一个实例,这意味着,在同一次HTTP会话内,程序每次请求该bean,得到的总是同一个实例。只有在Web应用中使用spring时,该作用域才真正的有效。

          global session:每个全局的HTTP Session对应一个bean实例。在典型的情况下,仅在使用portlet context的时候有效。只有在Web应用中使用spring时,该作用域才真正的有效。

          比较常用的是singleton和prototype。对于singleton作用域的bean,每次请求该bean都将获得相同的实例。容器负责跟踪bean实例的状态,负责维护bean实例的生命周期行为;对于prototype作用域的bean,程序每次请求该id的bean,spring都会新建一个bean实例,然后返回给程序。这种情况下,spring容器仅仅使用new关键字创建bean实例,一旦创建成功,容器就不再跟踪实例,也不会维护bean实例的状态。

          如果不指定bean的作用域,spring容器默认使用singleton作用域。

          spring配置文件通过scope属性指定bean的作用域,该属性可以接受singleton、prototype、request、session、globalSession五个值。

    3、request作用域

    4、session作用域

    5、配置依赖

         在依赖注入方式总结的时候,我们总结类两种依赖注入方式:

             设值注入:通过<property.../>元素驱动spring执行setter方法。

             构造注入:通过<constructor-arg.../>元素驱动spring执行带参数的构造器。

         对这两种设值方式的底层实现模拟:

         

         Person.java

    package com.lfy.bean;
    
    public class Person {
    
        private String name;
        private int age;
        
        /**
         * 定义一个无参构造器
         */
        public Person() {}
        
        /**
         * 定义一个带参构造器
         * @param name
         * @param age  构造器使用Integer,class字段属性是int
         */
        public Person(String name,Integer age) {
            this.name=name;
            this.age=age;
        }
        
        public void sayHello(String name) {
            
            System.out.println(name+",Hello.Nice to see you.");
        }
        
        public void selfIntroduction() {
            
            System.out.println("Hello,I am "+name+".I am "+age);
        }
    }

         ReflexTest.java

    package com.lfy.main;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    import com.lfy.bean.Person;
    
    /**
     * java反射的应用
     * @author lfy
     *
     */
    public class ReflexTest {
    
        public static void main(String[] args) {
    
            /**
             * spring设值注入底层代码实现简单例子
             */
            try {
                Class targetClass=Class.forName("com.lfy.bean.Person");
                try {
                    Object bean=targetClass.newInstance();
                    try {
                        String name="lfy";
                        Method targetMethod=targetClass.getMethod("sayHello", name.getClass());//这里演示没有使用Person.name的setter方法,但道理一样的
                        try {
                            targetMethod.invoke(bean, name);
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    }
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            
            /**
             * spring构造注入底层实现简单例子
             */
            try {
                Class targetClass=Class.forName("com.lfy.bean.Person");
                try {
                    String param1="lfy";
                    Integer param2=21;
                    Constructor targetCtr=targetClass.getConstructor(param1.getClass(),param2.getClass());
                    try {
                        //以指定构造器创建bean实例
                        Object bean=targetCtr.newInstance(param1,param2);
                        Person p=(Person)bean;
                        p.selfIntroduction();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (SecurityException e) {
                    e.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

         运行结果:

    6、自动装配注入合作者bean(即:被依赖bean),缺点是明显降低了配置文件的可读性

         <beans.../>元素下是default-autowire属性,<bean.../>元素下是autowire,它们可接受的值有:

          no:不使用自动装配。bean依赖必须通过ref元素定义,是默认配置。

          byName:根据setter方法名进行自动装配。spring容器查找容器中的全部bean,找出其id与setter方法名去掉set前缀,并小写字母后同名的bean来完成注入。如果没有匹配到任何bean实例,spring不会进行任何注入。

           byType:根据setter方法的形参类型来自动装配。spring容器查找容器中的全部bean,如果正好有一个bean类型与setter方法的形参类型匹配,就自动注入这个bean;如果找到多个这样的bean,就抛出一个异常;如果没有找到这样的bean,则什么都不发生,setter方法不会被调用。

           constructor:与byType类似,区别是用于自动匹配构造器的参数。如果容器不能恰好找到一个与构造器参数类型匹配的bean,则会抛出一个异常。

           autodetect:spring容器根据bean内部结构,自行决定使用constructor或byType策略。如果找到一个默认的构造器,那么就会应用byType策略。

    7、注入嵌套bean

          如果某个bean所依赖的bean不想被spring容器直接访问,则可以使用嵌套bean。

          将<bean.../>配置成<property.../>或<constructor-args.../>的子元素,则该bean仅作为设值注入、构造注入的参数,该bean就叫做嵌套bean。由于容器不能获取嵌套bean,故无需配置嵌套bean的id属性。

    8、注入集合值

         如果要被注入的值是集合类型,无论设值注入,还是构造注入,则可以使用集合元素<list.../>、<set.../>、<map.../>和<props.../>分别来设值类型为List、Set、Map和Properties的集合参数值。

         看个例子:

         

          beans.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
          
          <bean id="stoneAxe" class="com.lfy.impl.StoneAxe"/>
          <bean id="steelAxe" class="com.lfy.impl.SteelAxe"/>
          
          <bean id="chinese" class="com.lfy.impl.Chinese">
          
             <!-- List<String> -->
             <property name="schools">
                <list>
                   <!-- 每个value、ref、bean...都配置一个List元素  -->
                   <value>小学</value>
                   <value>中学</value>
                   <value>大学</value>
                </list>
             </property>
             
             <!-- Map -->
             <property name="scores">
                 <map>
                    <!-- 每个entry代表一个key-value对  -->
                    <entry key="数学" value="87"/>
                    <entry key="英语" value="89"/>
                    <entry key="语文" value="82"/>
                 </map>
             </property>
             
             <!-- Map<String,Axe> -->
             <property name="phaseAxes">
                 <map>
                    <entry key="原始社会" value-ref="stoneAxe"/>
                    <entry key="农业社会" value-ref="steelAxe"/>
                 </map>
             </property>
             
             <!-- Properties -->
             <property name="health">
                 <props>
                    <!-- 每个prop元素配置一个属性项,其中key指定属性名  -->
                    <prop key="血压">正常</prop>
                    <prop key="血压">175</prop>
                 </props>
             </property>
             
             <!-- Set -->
             <property name="axes">
                <set>
                   <!-- 每个value、ref、bean...都配置一个Set元素  -->
                   <value>普通的字符串</value>
                   <bean class="com.lfy.impl.SteelAxe"/>
                   <ref bean="stoneAxe"/>
                   <list>
                       <value>20</value>
                       <!-- 再次为List配置一个Set集合作为元素  -->
                       <set>
                          <value type="int">30</value>
                       </set>
                   </list>
                </set>
             </property>
             
             <!-- String[] -->
             <property name="books">
                <list>
                   <!-- 每个value、ref、bean...都配置一个数组元素  -->
                   <value>疯狂java讲义</value>
                   <value>疯狂Android讲义</value>
                   <value>轻量级java ee企业应用实战</value>
                </list>
             </property>
          </bean>
    </beans>

         stoneAxe.java

    package com.lfy.impl;
    
    import com.lfy.bean.Axe;
    
    public class StoneAxe implements Axe {
    
        @Override
        public String chop() {
            return "石斧砍柴好慢";
        }
    
    }

         steelAxe.java

    package com.lfy.impl;
    
    import com.lfy.bean.Axe;
    
    public class SteelAxe implements Axe {
    
        @Override
        public String chop() {
            return "钢斧砍柴真快";
        }
    
    }

         Chinese.java

    package com.lfy.impl;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    import java.util.Set;
    
    import com.lfy.bean.Axe;
    import com.lfy.bean.Person;
    
    public class Chinese implements Person {
    
        private Axe axe;
        private List<String> schools;
        private Map scores;
        private Map<String,Axe> phaseAxes;
        private Properties health;
        private Set axes;
        private String[] books;
        
        public Chinese() {
            
            System.out.println("spring实例化主调bean:Chinese实例...");
        }
        
        //设值注入所需的setter方法
        public void setAxe(Axe axe) {
            this.axe=axe;
        }
        
        public void setSchools(List schools) {
            this.schools=schools;
        }
        
        public void setScores(Map scores) {
            this.scores=scores;
        }
        
        public void setPhaseAxes(Map<String,Axe> phaseAxes) {
            this.phaseAxes=phaseAxes;
        }
        
        public void setHealth(Properties health) {
            this.health=health;
        }
        
        public void setAxes(Set axes) {
            this.axes=axes;
        }
        
        public void setBooks(String[] books) {
            this.books=books;
        }
        
        @Override
        public void useAxe() {
            //调用axe的chop()方法
            //表明Person对象依赖于axe对象
            System.out.println(axe.chop());
        }
        
        public void test() {
            
            System.out.println(schools);
            System.out.println(scores);
            System.out.println(phaseAxes);
            System.out.println(health);
            System.out.println(axes);
            System.out.println(Arrays.toString(books));
        }
    
    }

         springTest.java

    package com.lfy.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.lfy.impl.Chinese;
    
    public class SpringTest {
    
        public static void main(String[] args) {
    
            ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
            Chinese c=ctx.getBean("chinese", Chinese.class);
            c.test();
        }
    
    }

        运行结果:

     9、组合属性的设值

        举个例子,猫组合了一个主人相关的属性

         Chinese.java

    package com.lfy.impl;
    
    import com.lfy.bean.Person;
    
    public class Chinese implements Person {
    
        //姓名
        private String name;
        
        public String getName() {
            
            return name;
        }
        
        public void setName(String name) {
            
            this.name=name;
        }
    }

         Cat.java

    package com.lfy.impl;
    
    import com.lfy.bean.Animal;
    
    public class Cat implements Animal {
    
        //猫的主人是个中国人
        private Chinese chinese=new Chinese();
        
        public Chinese getChinese() {
            
            return chinese;
        }
    }

          beans.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
          
          <bean id="cat" class="com.lfy.impl.Cat">
             <property name="chinese.name" value="lfy"/>     
          </bean>
    </beans>

          SpringTest.java

    package com.lfy.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.lfy.impl.Cat;
    import com.lfy.impl.Chinese;
    
    public class SpringTest {
    
        public static void main(String[] args) {
    
            ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
            Cat c=ctx.getBean("cat", Cat.class);
            System.out.println("猫的主人的名字叫做:"+c.getChinese().getName());
        }
    
    }

         运行结果:

  • 相关阅读:
    关于vue中如何实现排到他思想
    js 文件下载
    js文件上传
    webpack学习笔记
    this总结
    React中props与state
    js事件总结
    js深拷贝与浅拷贝
    JS设计模式之观察者模式
    ES5与ES6的继承
  • 原文地址:https://www.cnblogs.com/ZeroMZ/p/11324701.html
Copyright © 2011-2022 走看看