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());
        }
    
    }

         运行结果:

  • 相关阅读:
    deeplearning.ai 卷积神经网络 Week 1 卷积神经网络
    deeplearning.ai 构建机器学习项目 Week 2 机器学习策略 II
    deeplearning.ai 构建机器学习项目 Week 1 机器学习策略 I
    deeplearning.ai 改善深层神经网络 week3 超参数调试、Batch Normalization和程序框架
    deeplearning.ai 改善深层神经网络 week2 优化算法
    deeplearning.ai 改善深层神经网络 week1 深度学习的实用层面
    cs231n spring 2017 lecture8 Deep Learning Networks
    cs231n spring 2017 lecture7 Training Neural Networks II
    cs231n spring 2017 lecture6 Training Neural Networks I
    cs231n spring 2017 Python/Numpy基础
  • 原文地址:https://www.cnblogs.com/ZeroMZ/p/11324701.html
Copyright © 2011-2022 走看看