@Bean 生命周期

bean生命周期:

@Bean 生命周期

实例bean

1.当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法;

2.根据配置情况调用Bean构造函数或工厂方法实例化Bean;

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

4.如果Bean配置了属性信息,容器在这一步着手将配置值设置到Bean对应的属性中,不过在设置每个属性之前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法;
**
**
初始化和使用bean

1:BeanNameAware的setBeanName():

如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。

2:BeanFactoryAware的setBeanFactory():

如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

3:BeanPostProcessors的ProcessBeforeInitialization()

如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。

4:initializingBean的afterPropertiesSet():

如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法

5:Bean定义文件中定义init-method:

可以在Bean定义文件中使用"init-method"属性设定方法名称例如:

如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法

6:BeanPostProcessors的ProcessaAfterInitialization()

如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法

BeanPostProcessor后处理器定义了两个方法:

**       其一是postProcessBeforeInitialization()在第8步调用;其二是Object postProcessAfterInitialization(Object bean, String beanName)方法,这个方法在此时调用,容器再次获得对Bean进行加工处理的机会;**

**       如果在中指定Bean的作用范围为scope="prototype",将Bean返回给调用者,调用者负责Bean后续生命的管理,Spring不再管理这个Bean的生命周期。如果作用范围设置为scope="singleton",则将Bean放入到Spring IoC容器的缓存池中,并将Bean引用返回给调用者,Spring继续对这些Bean进行后续的生命管理;**

 销毁bean

此时,Bean已经可以被应用系统使用,并且将保留在BeanFactory中知道它不在被使用。有两种方法可以将其从BeanFactory中删除掉

1:DisposableBean的destroy()

在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法

2:Bean定义文件中定义destroy-method

在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称,例如:

如果有以上设定的话,则进行至这个阶段时,就会执行destroy()方法,如果是使用ApplicationContext来生成并管理Bean的话则稍有不同,使用ApplicationContext来生成及管理Bean实例的话,在执行BeanFactoryAware的setBeanFactory()阶段后,若Bean类上有实现org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,接着才执行BeanPostProcessors的ProcessBeforeInitialization()及之后的流程。

代码:

package com.company;


import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import java.beans.PropertyDescriptor;

public class Main{
    public static void main(String[] args) {
        //①下面两句装载配置文件并启动容器
        Resource res = new ClassPathResource("beans.xml");
        BeanFactory bf = new XmlBeanFactory(res);
        
        //②向容器中注册MyBeanPostProcessor后处理器
        ((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());

        //③向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
        ((ConfigurableBeanFactory)bf).addBeanPostProcessor(
                new MyInstantiationAwareBeanPostProcessor());
        //④第一次从容器中获取worker,将触发容器实例化该Bean,这将引发Bean生命周期方法的调用。
        Worker worker1 = (Worker)bf.getBean("worker");
        System.out.println("第一次从容器中获取worker");
        worker1.printInfo();
        System.out.println("修改第一次从容器中获取worker的workType");
        worker1.setWorkType("正式工");
        System.out.println("第一次从容器中获取worker(修改过后的)");
        worker1.printInfo();
        //⑤第二次从容器中获取worker,直接从缓存池中获取
        System.out.println("第二次从容器中获取worker");
        Worker worker2= (Worker)bf.getBean("worker");
        worker2.printInfo();
        //⑥查看worker1和worker2是否指向同一引用
        System.out.println("查看worker1和worker2是否指向同一引用    ");
        System.out.println("worker1==worker2:"+(worker1==worker2));
        //⑦关闭容器
        ((XmlBeanFactory)bf).destroySingletons();
    }

}
    //①管理Bean生命周期的接口
       class Worker implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean {
        private String name;
        private String workType;
        private int salary;

        public BeanFactory beanFactory;
        private String beanName;

        public void Worker(){
            System.out.println("调用worker()构造函数");
        }

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getWorkType() {
            return workType;
        }
        public void setWorkType(String workType) {
            this.workType = workType;
        }
        public int getSalary() {
            return salary;
        }
        public void setSalary(int salary) {
            this.salary = salary;
        }
        public void printInfo() {
            System.out.println("name:" + name + ";workType:" + workType + ";salary:"
                    + salary);
        }
        //⑤DisposableBean接口方法
        @Override
        public void destroy() throws Exception {
            System.out.println("----------------销毁bean----------------------");
            System.out.println("调用DisposableBean.destroy()。");

        }
        //④InitializingBean接口方法
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("调用InitializingBean.afterPropertiesSet()。");

        }
        //③BeanNameAware接口方法
        @Override
        public void setBeanName(String arg0) {
            System.out.println("----------------初始化bean----------------------");
            System.out.println("调用BeanNameAware.setBeanName()。");
            this.beanName = arg0;

        }
        //②BeanFactoryAware接口方法
        @Override
        public void setBeanFactory(BeanFactory arg0) throws BeansException {
            System.out.println("调用BeanFactoryAware.setBeanFactory()。");
            this.beanFactory = arg0;
        }

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

        //⑦通过<bean>的destroy-method属性指定的销毁方法
        public void myDestroy() {
            System.out.println("调用destroy-method所指定的myDestroy()。");
        }

    }

     class MyBeanPostProcessor implements BeanPostProcessor {

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName)
                throws BeansException {
            if(beanName.equals("worker")){
                Worker worker = (Worker)bean;
                if(worker.getWorkType() == null){
                    System.out.println("调用BeanPostProcessor.postProcess AfterInitialization(),  getWorkType为空,设置为默认临时工");
                    worker.setWorkType("临时工");
                }
            }
            return bean;
        }

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName)
                throws BeansException {
            if(beanName.equals("worker")){
                Worker worker = (Worker)bean;
                if(worker.getSalary() >= 1000){
                    System.out.println("调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。");
                    worker.setSalary(800);
                }
            }
            return bean;
        }

    }

      class MyInstantiationAwareBeanPostProcessor extends
            InstantiationAwareBeanPostProcessorAdapter {
        // ①接口方法:在实例化Bean前进行调用
        public Object postProcessBeforeInstantiation(Class beanClass,
                                                     String beanName) throws BeansException {
            System.out.println("----------------实例化bean----------------------");
            // ①-1仅对容器中worker Bean进行处理
            if ("worker".equals(beanName)) {
                System.out
                        .println("InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation");
            }
            return null;
        }

        // ②接口方法:在实例化Bean后调用
        public boolean postProcessAfterInstantiation(Object bean, String beanName)
                throws BeansException {
            // ②-1仅对容器中car Bean进行处理
            if ("worker".equals(beanName)) {
                System.out
                        .println("InstantiationAware BeanPostProcessor.postProcess AfterInstantiation");
            }
            return true;
        }

        // ③接口方法:在设置某个属性时调用
        public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                                                        PropertyDescriptor[] pds, Object bean, String beanName)
                throws BeansException {

            // ③-1仅对容器中wroker Bean进行处理,还可以通过pdst入参进行过滤,
            // 仅对car的某个特定属性时进行处理。
            if ("worker".equals(beanName)) {
                System.out
                        .println("Instantiation AwareBeanPostProcessor.postProcess PropertyValues");
            }
            return pvs;
        }
    }

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    <bean >
          init-method="myInit"
          destroy-method="myDestroy"
          p:name="小强"
          p:salary="1000"
    />
</beans>

Result:

----------------实例化bean----------------------
InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation
InstantiationAware BeanPostProcessor.postProcess AfterInstantiation
Instantiation AwareBeanPostProcessor.postProcess PropertyValues
----------------初始化bean----------------------
调用BeanNameAware.setBeanName()。
调用BeanFactoryAware.setBeanFactory()。
调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。
调用InitializingBean.afterPropertiesSet()。
调用init-method所指定的myInit(),将salary设置为600。
调用BeanPostProcessor.postProcess AfterInitialization(),  getWorkType为空,设置为默认临时工
第一次从容器中获取worker
name:小强;workType:临时工;salary:600
修改第一次从容器中获取worker的workType
第一次从容器中获取worker(修改过后的)
name:小强;workType:正式工;salary:600
第二次从容器中获取worker
name:小强;workType:正式工;salary:600
查看worker1和worker2是否指向同一引用    
worker1==worker2:true
----------------销毁bean----------------------
调用DisposableBean.destroy()。
调用destroy-method所指定的myDestroy()。

http://www.kancloud.cn/evankaka/springlearning/119661

http://www.imooc.com/article/19449

https://my.oschina.net/guanhe/blog/1408505

http://blog.csdn.net/mack415858775/article/details/47721909

https://zhuanlan.zhihu.com/p/25459839

https://muyinchen.github.io/2017/08/23/Spring5%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90-@Autowired/

http://www.shangyang.me/2017/04/05/spring-core-container-sourcecode-analysis-annotation-autowired/