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

}

     运行结果:

转载于:https://www.cnblogs.com/ZeroMZ/p/11324701.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值