spring-第七篇之深入理解容器中的bean

1、抽象bean与子bean

      用于指定配置模板。

2、容器中的工厂bean

      这种工厂bean必须实现FactoryBean接口,通过spring容器getBean()方法获取它时,容器返回的不是FactoryBean实现类的实例,而是返回FactoryBean的产品(即该工厂bean的getObject()方法的返回值,至于该方法返回什么东西,使我们重写该方法时决定的,一般是工厂bean生成的实例)。

      FactoryBean接口提供了3个方法:

        1》T getObject():实现该方法返回该工厂bean生成的java实例。

        2》Class<?> getObjectType():实现该方法返回该工厂bean生成的java实例的实现类。

        3》bolean isSingleton():实现该方法表示该工厂bean生成的java实例是否为单例模式。

      举一例子:

      GetFieldFactoryBean.java

package com.lfy.bean;

import java.lang.reflect.Field;

import org.springframework.beans.factory.FactoryBean;

public class GetFieldFactoryBean implements FactoryBean<Object> {
    
   private String targetClass;
   private String targetField; public void setTargetClass(String targetClass) { this.targetClass=targetClass; } public void setTargetField(String targetField) { this.targetField=targetField; } /** * 返回工厂bean所生产的产品 */ @Override public Object getObject() throws Exception{ Class<?> clazz=Class.forName(targetClass); Field field=clazz.getField(targetField); return field.get(null); } /** * 获取工厂bean所生产的产品的类型 */ @Override public Class<? extends Object> getObjectType() { return Object.class; } /** * 返回该工厂bean所生产的产品是否为单例 */ @Override public boolean isSingleton() { return false; } }

     Cat.java

package com.lfy.bean;

public class Cat {

    //品种:猫
    public static final String variety="猫";
    
    //叫声:有可能是“喵喵”,也有可能是其他的
    public static String voice="喵喵";
}

    Dog.java

package com.lfy.bean;

public class Dog {

    //品种:狗
    public static final String variety="狗";
    
    //叫声:有可能是“汪汪”,也有可能是其他的
    public static String voice="汪汪";
}

     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.bean.GetFieldFactoryBean">
         <property name="targetClass" value="com.lfy.bean.Cat"/>
         <property name="targetField" value="voice"/>
      </bean>
      
      <bean id="dog" class="com.lfy.bean.GetFieldFactoryBean">
         <property name="targetClass" value="com.lfy.bean.Dog"/>
         <property name="targetField" value="voice"/>
      </bean>
</beans>

     SpringTest.java

package com.lfy.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 容器中的工厂bean
 * @author lfy
 *
 */
public class SpringTest {

    public static void main(String[] args) {
        
        ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); System.out.println(ctx.getBean("cat")); System.out.println(ctx.getBean("dog")); System.out.println(ctx.getBean("&dog")); } }

     运行结果:

    总结:spring容器会自动检测容器中的所有bean,如果发现某个bean实现类(如:GetFieldFactoryBean)实现了FactoryBean接口,spring容器就会在实例化该bean,根据<property.../>执行setter方法之后,额外调用该bean的getObject()方法,并将该方法的返回值作为容器中的bean。

    对于在ApplicationContext.getBean()方法使用&符号,将会得到FactoryBean本身,而不是它的产品。

3、获取bean本身的部署id

    实现BeanNameAware接口,其中的方法setBeanName(String name)方法会在容器检查到目标bean实现了BeanNameAware接口的时候(目标bean已经实例化完成),自动调用该方法,并将目标bean部署时的id作为参数传入到该方法中。

    举个例子:

    

    Chinese.java

package com.lfy.bean;

import org.springframework.beans.factory.BeanNameAware;

public class Chinese implements BeanNameAware {

    private String beanName;
    
    @Override
    public void setBeanName(String beanName) {
        
        this.beanName=beanName; } public void info() { System.out.println("Chinese实现类"+",部署该bean时指定的id为:"+beanName); } }

    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="chin" class="com.lfy.bean.Chinese"></bean>
</beans>

     SpringTest.java

package com.lfy.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.lfy.bean.Chinese;

/**
 * 获得bean本身的id
 * @author lfy
 *
 */
public class SpringTest {

    public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); Chinese chin=ctx.getBean("chin", Chinese.class); chin.info(); } }

    运行结果:

 4、强制初始化bean

     某些时候需要被依赖bean先于目标bean初始化,可以使用depends-on属性,该属性可以强制初始化一个或者多个被依赖的bean。

猜你喜欢

转载自www.cnblogs.com/ZeroMZ/p/11335661.html