Spring bean的生命周期深入理解

面对别人问你Spring的生命周期怎么回答他?

谈到 bean 的生命周期,概括为分为四个阶段:
1、bean的实例化 Instantiation
2、给属性值赋值 Populate
3、初始化 initialization
4、销毁 Destory

阅读源码发现在AbstractBeanFactory类中的doCreateBean()中有对这几个阶段的方法调用,忽略了无关代码,方便理解,如下:

// 忽略了无关代码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (instanceWrapper == null) {
       // 实例化阶段!
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
       // 属性赋值阶段!
      populateBean(beanName, mbd, instanceWrapper);
       // 初始化阶段!
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
 }

实例化和属性赋值对应构造方法和setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段。销毁阶段是在容器关闭时调用的,在ConfigurableApplicationContext类的close()中。

举例

下面,实现一下InitializingBean、BeanNameAware、ApplicationContextAware、BeanFactoryAware这几个接口,来重写对应接口下的方法。
首先写个Car实体类,分别实现InitializingBean接口的init、destroy方法,重写BeanNameAware 接口的setBeanName方法,ApplicationContextAware接口的setApplicationContext方法,BeanFactoryAware接口的setBeanFactory方法。

/*
 * 一个类必须要有构造方法!!!  FactoryBean 
 */
public class Car  implements InitializingBean ,BeanNameAware ,
ApplicationContextAware,BeanFactoryAware{
    private String  name;
    private String beanName;
    
   //1、jvm自动为这个类添加一个无参数的默认构造方法
    //public Car() {}
    //2、自己写构造方法,jvm不会自动添加构造方法了
    public Car() {
        //System.out.println("car实例化");
    }
    public Car(String name) {
        super();
        System.out.println("car实例化");
        this.name = name;
    }
    /*初始化方法*/
    public void init() {
        System.out.println("car进行初始化。");
    }
    
    public void destroy() {
        System.out.println("car进行销毁。");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet  被调用的.....");
    }
    //重写BeanNameAware的方法
    public void setBeanName(String name) {
        this.beanName = name;
    }
    public String  getBeanName() {
        return beanName;
    }
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext:"+applicationContext);
    }
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("beanFactory====>"+beanFactory);
    }
    
}
@Configuration
public class MainConfig {
    @Bean(name="car",initMethod="init",destroyMethod="destroy")
    public Car getCar() {
        return new Car("大黄蜂");
    }
    
    @Bean
    public BeanPostProcessor getBeanPostProcessor() {
        return new NdBeanPostProcessor();
    }
    
    @Bean
    public InstantiationAwareBeanPostProcessorAdapter getIntanceAware(){
        return new MyInstantiationAwareBeanPostProcessorAdapter();
    }
    
}

在实例化前后,初始化前后进行干预。

public class MyInstantiationAwareBeanPostProcessorAdapter extends InstantiationAwareBeanPostProcessorAdapter {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("car")){
            System.out.println("【实例化】【前】干预"+beanName);
        }
        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("car")){
            System.out.println("【初始化】【前】干预"+beanName);
        }
        return super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("car")){
            System.out.println("【初始化】【后】干预"+beanName);
        }
        return bean;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("car")){
            System.out.println("【实例化】【后】干预"+beanName);
        }
        return super.postProcessAfterInstantiation(bean, beanName);
    }

}

四个主生命周期
(1)实例化之前干预 InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInstantiation()
1.实例化
(2)实例化之后干预 InstantiationAwareBeanPostProcessorAdapter
.postProcessAfterInstantiation()
2.填充属性(给属性赋值)

(1)初始化之前干预 BeanPostProcessor.postProcessBeforeInitialization()
(3) InitializingBean.afterPropertiesSet()
3.初始化(比如准备资源文件)
(2)初始化之后干预 BeanPostProcessor.postProcessAfterInitialization()
4.销毁(释放资源—对象从内存销毁)


/*
 四个主生命周期
         (1)实例化之前干预     InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInstantiation()
     1.实例化
          (2)实例化之后干预   InstantiationAwareBeanPostProcessorAdapter.postProcessAfterInstantiation()
     2.填充属性(给属性赋值)
             ()
          (1)初始化之前干预   BeanPostProcessor.postProcessBeforeInitialization()
             (3)  InitializingBean.afterPropertiesSet()
     3.初始化(比如准备资源文件)
             
         (2)初始化之后干预    BeanPostProcessor.postProcessAfterInitialization()
         
     4.销毁(释放资源---对象从内存销毁)
 N个接口
     1、干预多次
         1)BeanPostProcessor
     2、干预一次
         1)Aware
     
 */
public class TestLifeCycle {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
                new AnnotationConfigApplicationContext(MainConfig.class);
        Car car = (Car) context.getBean("car");
        System.out.println(car);//toString
        
        System.out.println("car bean的名字叫:"+car.getBeanName());
        
        
       // Car car1 = new Car();//不会干预  因为你不是交给spring ioc容器进行实例化
    }
}

后置处理器的postProcessBeforeInitialization、postProcessBeforeInitialization方法。

//后置处理器
public class NdBeanPostProcessor implements BeanPostProcessor{


	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("NdBeanPostProcessor在car对象初始化之 前 调用");
		if(beanName.equals("car")) {
			return new CglibInterceptor().getInstance(bean.getClass());
		}
		return bean;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("NdBeanPostProcessor在car对象初始化之 后 调用");
		return bean;
	}

}

CGLIB动态代理拦截器,

public class CglibInterceptor  implements  MethodInterceptor{

    public Object getIntance(Class clazz) {
        Enhancer enchncer = new Enhancer();
        enchncer.setSuperclass(clazz);
        enchncer.setCallback(this);
        return enchncer.create();
    }
    
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("-----鉴权前-----");
        Object result =  proxy.invokeSuper(obj, args);
        System.out.println("-----鉴权后-----");
        return result;
    }

}

运行结果如图所示,
在这里插入图片描述

总结为

Bean 生命周期的整个执行过程描述如下。
1)根据配置情况,如果在配置文件内配置了InstantiationAwareBeanPostProcessorAdapter类,在干预类中继承了该类,那么可重写该类的postProcessBeforeInstantiation()方法。

2)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。

3)如果在配置文件内配置了
InstantiationAwareBeanPostProcessorAdapter类,在干预类中继承了该类,
那么可重写该类的postProcessAfterInstantiation()方法。

4)利用依赖注入完成 Bean 中所有属性值的配置注入。

5)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。

6)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用(即将BeanFactory对象传给setBeanFactory方法)。

7)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。

8)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作。此处非常重要,Spring 的 AOP 就是利用它实现的。

9)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。

10)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。

11)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。

12)如果在配置文件的Bean标签 中指定了该 Bean 的作用范围为 scope=“singleton”,则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在配置文件的Bean标签指定了该 Bean 的作用范围为 scope=“prototype”,则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。

13)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。

另外,个人从[https://www.jianshu.com/p/1dec08d290c1]文章中受益不少,部分转载其中,如有侵权,可沟通删除。读者读后看哪些需要补充的,欢迎不吝赐教。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值