程序员社区

Spring:Bean的生命周期

文章目录

      • Spring Bean的生命周期
        • 1、示例引入
          • 1、定义bean
          • 2、后置处理器1
          • 3、后置处理器2
          • 4、beans.xml的配置
          • 5、注册两个后置处理器
        • 2、BeanFactory中bean的生命周期
        • 3、ApplicationContext中bean的生命周期

Spring Bean的生命周期

1、示例引入

1、定义bean
//定义一个Car,实现Bean的4个生命周期级接口
public class Car implements BeanFactoryAware, BeanNameAware,
        InitializingBean, DisposableBean {

    private String brand;
    private String color;
    private int maxSpeed;

    private BeanFactory beanFactory;
    private String beanName;

    public Car() {
        System.out.println("调用Car()的构造函数");
    }

    public void setBrand(String brand) {
        System.out.println("调用setBrand()方法");
        this.brand = brand;
    }

    public void introtuce() {
        System.out.println( "brand:" + brand + ";color:'" + color +";maxSpeed:" + maxSpeed);
    }

    //1、BeanFactoryAware接口:注入一个工厂对象
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("调用BeanFactoryAware.setBeanFactory()。");
        this.beanFactory = beanFactory;
    }

    //2、BeanNameAware接口:setBeanName(String name)注入bean的名称
    @Override
    public void setBeanName(String name) {
        System.out.println("调用BeanNameAware.setBeanName()。");
        this.beanName = name;
    }

    //3、InitializingBean接口:完成初始化逻辑
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用InitializingBean.afterPropertiesSet()。");
    }

    //4、DisposableBean接口:完成销毁逻辑
    @Override
    public void destroy() throws Exception {
        System.out.println("调用DisposableBean.destroy()。");

    }

    //5、通过<bean>的init_method属性指定初始化方法
    public void myInit(){
        System.out.println("调用init-method所指定的myInit(),将maxSpeed设置为240");
        this.maxSpeed=240;
    }

    //6、通过<bean>的destory_method属性指定销毁方法
    public void myDestory(){
        System.out.println("调用destory-method所指定的myDestory()");
    }

...省略get()set()方法.....
}
2、后置处理器1
/**
 * 在这个类中通过过滤条件仅对car Bean进行处理,对其他Bean一概视而不见
 */
public class MyInstantiationAwareBeanPostProcessor
        extends InstantiationAwareBeanPostProcessorAdapter {
    /**
     * 1、父类方法:在实例化Bean之前调用
     */
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        //仅对容器中的Car bean做处理
        if("car".equals(beanName)){
            System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()");
        }
        return null;
    }

    /**
     * 2、父类方法:在实例化Bean之后调用
     */
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        //仅对容器中Car Bean处理
        if("car".equals(beanName)){
            System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()");
        }
        return true;
    }

    /**
     * 3、父类方法:在设置某个属性时调用
     */
    @Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        //仅对car中某个特定属性进行处理
        if(beanName.equals("car")){
            System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues()");
        }
        return pvs;
    }
}
3、后置处理器2
/**
 * 在这个类中仅对Car Bean进行处理:
 *      对配置文件所提供的属性设置值进行判断,并执行相应的“补缺查漏”操作
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("car")){
            Car car = (Car) bean;
            if(car.getColor()==null){
                System.out.println("调用MyBeanPostProcessor.postProcessBeforeInitialization() ,color为空,设置为黑色");
                car.setColor("黑色");
            }

        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("car")){
            Car car = (Car) bean;
            if(car.getMaxSpeed()>=200){
                System.out.println("调用MyBeanPostProcessor.postProcessAfterInitialization() ,将maxSpeed调整为200");
                car.setMaxSpeed(200);
            }
        }
        return bean;
    }
}
4、beans.xml的配置
<bean id="car"
      class="com.hh.bean.Car"
      init-method="myInit"
      destroy-method="myDestory">
    <property name="brand" value="红旗CA72"/>
    <property name="maxSpeed" value="200"/>
</bean>
5、注册两个后置处理器

让容器装载配置文件,然后分别注册上面所提供的两个后置处理器,这里是Bean的生命周期的关键:

/**
 * 让容器装载配置文件,然后分别注册上面所提供的两个后置处理器
 *
 * 1、对BeanFactory类型的beanFactory变量进行强制装换,
 *      是因为addBeanPostProcessor()在ConfigurableBeanFactory接口中
 * 2、后置处理器的时机地哦啊用顺序和注册顺序无关,在有多个后置处理器的情况下
 *    必须通过实现org.springframework.core.Ordered接口来确定调用顺序
 *
 * 3、第一次获取bean,容器将按照生命周期过程,实例化Car并放入缓存池中,然后返回给调用者
 *    第二次从容器中获取Car,直接从缓存池中获取,不会引发生命周期相关方法的执行
 *    如果将scope=prototype,第二次获取bean时,生命周期方法会再次被调用,因为每次返回新实例
 */
public class BeanLifeCycle {
    public static void main(String[] args) {
        LifeCycleInBeanFactory();
    }

    public static void LifeCycleInBeanFactory(){
        //1、封装配置文件:将配置文件封装为Resource类型的实例方法
        Resource res = new ClassPathResource("beans.xml");

        //2、启动容器:xmlBeanFactory的初始化
        BeanFactory beanFactory = new DefaultListableBeanFactory();

        //3、加载配置文件
        XmlBeanDefinitionReader reader
                = new XmlBeanDefinitionReader((DefaultListableBeanFactory)beanFactory);
        reader.loadBeanDefinitions(res);

        //4、向容器中注册MyBeanPostProcessor后处理器
        ((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyBeanPostProcessor());

        //5、向容器中注册MyInstantiationAwareBeanPostProcessor
        ((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

        //6、第一次从容器中获取car,将触发容器初始化Bean,将引发Bean生命周期方法的调用
        Car car1 = (Car) beanFactory.getBean("car");
        car1.introtuce();
        car1.setColor("红色");

        //7、第二次从容器中获取Car,直接从缓存池中获取
        Car car2 = (Car)beanFactory.getBean("car");
        System.out.println("car1==car2:"+ (car1==car2));

        //8、关闭容器
        ((DefaultListableBeanFactory)beanFactory).destroySingletons();
    }
}

运行结果:

调用MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
调用Car()的构造函数
调用MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
调用MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues()
调用setBrand()方法
调用BeanNameAware.setBeanName()。
调用BeanFactoryAware.setBeanFactory()。
调用MyBeanPostProcessor.postProcessBeforeInitialization() ,color为空,设置为黑色
调用InitializingBean.afterPropertiesSet()。
调用init-method所指定的myInit(),将maxSpeed设置为240
调用MyBeanPostProcessor.postProcessAfterInitialization() ,将maxSpeed调整为200
brand:红旗CA72;color:'黑色;maxSpeed:200
car1==car2:true
调用DisposableBean.destroy()。
调用destory-method所指定的myDestory()

2、BeanFactory中bean的生命周期

在这里插入图片描述

  1. 当调用者通过getbean(beanName)向容器中请求一个Bean时,如果容器注册了InstantiationAwareBeanPostProcessor接口,就会在Bean实例化之前调用接口的postProcessBeforeInstantiation()方法

  2. 根据情况调用Bean构造方法或者工厂方法实例化Bean

  3. 如果容器注册了InstantiationAwareBeanPostProcessor,实例化Bean后,调用该接口的postProcessAfterInstantiation()方法,可在这里对已经实例化的Bean进行一些"梳妆打扮"

  4. 如果Bean配置了属性信息,那么容器会将配置值设置到对应的属性中,不过在设置每个属性之前会调用postProcessPropertyValues()方法。

  5. 调用bean 的属性设置方法设置属性

  6. 如果Bean实现了BeanNameAwae接口,将调用setBeanName()接口方法,将配置文件该Bean对应的名称设置到bean中

  7. 如果Bean实现了BeanFactoryAware接口,将调用setBeanFactory()接口方法,将BeanFactory容器实例设置到Bean中。

  8. 如果BeanFactory装配了BeanPostProcessor后处理器,将调用BeanPostProcessorpostProcessBeforeInitialization(Object bean,String beanName)接口方法对bean进行加工操作,其中入参是当前正在处理的bean,而beanName是当前Bean的配置名,返回的Bean为加工处理后的bean,用户可以会用该方法对某些Bean进行特殊处理,甚至改变Bean的行为。BeanPostProcessor在Spring中占有重要的地位,为容器提供对Bean进行后续护理的切入点,Spring的AOP、动态代理都通过BeanPostProcessor完成。

  9. 如果bean实现了InitializingBean接口,将调用接口的afterPropertiesSet()方法。

  10. 如果在<bean>中通过init-method属性定义了初始化方法,则执行这个方法。

  11. BeanPostProcessor中定义了两个方法,一个在第8步执行,另一个在这里执行postProcessAfterInitialization(Object bean, String beanName),容器再次获得对bean进行加工处理的机会。

  12. 如果<bean>中指定bean的作用范围为scope=“prototype”,则将Bean返回给调用者,调用者负责bean后续生命的管理,Spring不再管理这个Bean生命周期。如果将scope=“Singleton”,则将bean放入SpringIOC容器的缓存池中,并将bean引用返回给调用者,Spring继续对这些Bean进行管理。

  13. 对于scope=“Singleton”,当容器关闭时,将处罚Spring对bean后续生命周期的管理工作,如果Bean实现了DisposableBean接口,将调用接口的destroy()方法。可以在此编写释放资源,记录日志等。

  14. 对于scope=“Singleton”,如果在<bean>中通过destory-method属性定义销毁化方法,则执行这个方法。

3、ApplicationContext中bean的生命周期

在这里插入图片描述

1、Bean在ApplicationContext中的生命周期和在BeanFactory中的生命周期类似,不同的是如果Bean实现了ApplicationContextAware接口,会增加一个接口方法setApplicationContext()

public class Car implements ApplicationContextAware, BeanNameAware,
        InitializingBean, DisposableBean {
    //属性     
    private ApplicationContext applicationContext;

    //1、新增的ApplicationContext接口方法:setApplicationContext()
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
....重复方法和属性省略.......
}

2、如果在配置文件中声明了工厂后处理接口BeanFactoryPostProcessor的实现类,则应用上下文在装配配置文件之后、初始化Bean实例之前将调用这些BeanFactoryPostProcessor对配置信息进行加工处理。工厂后处理器是容器级的,仅在应用上下文初始化时调用一次,其目的地完成一一些配置文件的加工处理工作。更改配置信息。

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("car");
        beanDefinition.getPropertyValues().addPropertyValue("brand","奇瑞QQ");
        System.out.println("调用BeanFactoryPostProcessor.postProcessBeanFactory()!");
    }
}

3、ApplicationContextBeanFactory另一个最大的不同之处在于:前者会利用j反射机制自动识别出配置文件中定义的BeanFactoryPostProcessorInstantiationAwareBeanPostProcessorBeanPostProcessor而后者需要在代码中手工调用addBeanPostProcessor()方法进行注册。

    <bean id="car" class="com.hh.bean.Car" init-method="myInit" destroy-method="myDestory">
        <property name="brand" value="红旗CA72"/>
        <property name="maxSpeed" value="200"/>
    </bean>
    <!--配置工厂后处理器-->
    <bean id="myBeanPostProcessor" class="com.hh.beanfactory.MyBeanPostProcessor"/>
    <!--注册Bean后处理器-->
    <bean id="myBeanFactoryPostProcessor" class="com.hh.beanfactory.MyBeanFactoryPostProcessor"/>
	<!--注册Bean后处理器-->
    <bean id="myInstantiationAwareBeanPostProcessor" class="com.hh.beanfactory.MyInstantiationAwareBeanPostProcessor"/>
<!--
说明:这种不是自己写的类,jar包中的类如果想放入容器又不使用配置文件,
		 需要使用配置类:@Configuration+@Bean
-->

4、ApplicationContext在启动时首先为配置文件中的每个<bean>生成一个BeanDefinition对象,BeanDefinition<bean>在Spring中的内部表示,当配置文件中的所有<bean>被解析成BeanDefinition后,ApplicationContext将调用工厂后处理器的方法,因此有机会通过程序的方式,调整Bean的配置信息。

public class BeanLifeCycle {
    public static void main(String[] args) {
        LifeCycleInBeanFactory();
    }

    public static void LifeCycleInBeanFactory(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        
        //第一次从容器中获取car,将触发容器初始化Bean,将引发Bean生命周期方法的调用
        Car car1 = (Car) context.getBean("car");
        car1.introtuce();
        car1.setColor("红色");

        //第二次从容器中获取Car,直接从缓存池中获取
        Car car2 = (Car)context.getBean("car");
        System.out.println("car1==car2:"+ (car1==car2));
    }
}

结果:

调用BeanFactoryPostProcessor.postProcessBeanFactory()!
调用MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
调用Car()的构造函数
调用MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
调用MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues()
调用setBrand()方法
调用BeanNameAware.setBeanName()。
调用MyBeanPostProcessor.postProcessBeforeInitialization() ,color为空,设置为黑色
调用InitializingBean.afterPropertiesSet()。
调用init-method所指定的myInit(),将maxSpeed设置为240
调用MyBeanPostProcessor.postProcessAfterInitialization() ,将maxSpeed调整为200
brand:奇瑞QQ;color:'黑色;maxSpeed:200
car1==car2:true

赞(0) 打赏
未经允许不得转载:IDEA激活码 » Spring:Bean的生命周期

相关推荐

  • 暂无文章

一个分享Java & Python知识的社区