spring bean的生命周期有哪些?有什么可扩展的?

30 篇文章 0 订阅
6 篇文章 0 订阅

spring bean 的生命周期

在scope为单例模式下,spring bean的生命周期如下图
在这里插入图片描述

从代码中对照

class AbstractAutowireCapableBeanFactory

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

上述流程位置追踪:
在这里插入图片描述

具体来说:

1.首先实例化bean对象。

如果是beanFactory容器,当客户请求一个尚未实例化的bean时,或需要依赖注入一个尚未实例化的bean时,容器会通过调用createBean进行该bean的实例化。
对于ApplicationContext容器,在容器启动结束后,就会实例化所有bean。
容器通过调用beanDefinition获取bean信息进行实例化,此步骤仅仅是简单的实例化,并未进行依赖注入。

2.设置对象属性,进行依赖注入。
依赖注入过程及如何避免循环依赖的,可见我之前的文章。

3.检查Aware相关接口,设置相关依赖。

这一步主要检查以下几个接口,
BeanNameAware接口,如果实现了该接口,会调用setBeanName(String beanId)方法,将beanId传进来。
BeanFactoryAware接口,如果实现了该接口,会调用setBeanFactory()方法,将容器本身传进来。(可以用该容器获取到其他bean)
ApplicationContextAware接口,如果实现了该接口,会调用SetApplicationContext(ApplicationContext)方法,传入spring上下文,即ApplicationContext这个容器。ApplicationContext是BeanFactory的子类,有更多方法,更易于使用。

经过以上几步,bean已经被正确的构造了,如果你想在使用前再增加一些自定义方法,可以使用以下步骤。

4.BeanPostProcesssor接口

如果bean实现了BeanPostProcesssor接口,则调用前置处理方法。
即PostProcessBeforeInitialzation(Object bean,String beanName),当前初始化的bean被传进来,我们就可以进行自定义设置了。由于此步设置发生在InitialzationBean方法之前执行,所以成为前置处理。
对应的PostProcessAfterIntialzation(Object bean,String beanName)即是后置处理

5.如果实现了InitialzationBean接口。

该接口只有一个方法,即afterPropertiesSet(),执行该方法。
该步骤跟BeanPostProcessor接口不通,本步骤没有传入bean,所以我们无法处理bean本身,只能添加一些相关的业务逻辑。
使用InitialzationBean的方式有两种,一个是直接实现该接口,在实现方法中写业务逻辑。
还有一种便捷方法,可以减少代码入侵。即使用init-method注解,使用该属性指向我们的自定义方法。这样在bean初始化时便会执行对应的方法。
先执行afterPropertiesSet()方法,再执行init-method()方法

6.如果实现了BeanPostProcessor接口,调用后置方法。

即调用PostAfterInitialzation(Obeject bean,String beanName)方法

此时bean已经准备就绪了,可以被应用程序使用了,它将一直驻留在上下文中,知道容器被销毁。

7.如果bean实现了DisposableBean接口

则在销毁该bean之前,调用对应的实现方法destory()。
跟InitialzationBean接口对应,也有一个对应的destory-method,指定对应的方法。就可以在销毁bean前执行对应的逻辑了。
执行destory()方法,再执行destory-method方法。

以上就是spring bean的生命周期了。

talk is cheap,show me the code!

下面是每一步具体的应用举例

*实现 Aware 接口

@Component
public class SpringLifeCycleAware implements ApplicationContextAware {
    private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleAware.class);

    private ApplicationContext applicationContext ;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext ;
        LOGGER.info("SpringLifeCycleAware start");
    }
}

BeanPostProcessor 增强处理器

@Component
public class SpringLifeCycleProcessor implements BeanPostProcessor {
    private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleProcessor.class);

    /**
     * 预初始化 初始化之前调用
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("annotationBean".equals(beanName)){
            LOGGER.info("SpringLifeCycleProcessor start beanName={}",beanName);
        }
        return bean;
    }

    /**
     * 后初始化  bean 初始化完成调用
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("annotationBean".equals(beanName)){
            LOGGER.info("SpringLifeCycleProcessor end beanName={}",beanName);
        }
        return bean;
    }
}

InitializingBean, DisposableBean 接口

@Service
public class SpringLifeCycleService implements InitializingBean,DisposableBean{
    private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleService.class);
    @Override
    public void afterPropertiesSet() throws Exception {
        LOGGER.info("SpringLifeCycleService start");
    }

    @Override
    public void destroy() throws Exception {
        LOGGER.info("SpringLifeCycleService destroy");
    }
}

自定义初始化和销毁方法

@Configuration
public class LifeCycleConfig {


    @Bean(initMethod = "start", destroyMethod = "destroy")
    public SpringLifeCycle create(){
        SpringLifeCycle springLifeCycle = new SpringLifeCycle() ;

        return springLifeCycle ;
    }
}

public class SpringLifeCycle{

    private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycle.class);
    public void start(){
        LOGGER.info("SpringLifeCycle start");
    }


    public void destroy(){
        LOGGER.info("SpringLifeCycle destroy");
    }
}

OK,现在用例也有了,那么问题来了

spring bean生命周期有什么可扩展的?

spring bean生命周期中有很多可以扩展的地方。
比如我们可以将生命周期简单归为以下步骤

实例化-》属性填充-》执行Aware接口-》初始化-》应用-》销毁

那么如果我们实现了BeanPostProcessor子类InstantiationAwareBeanPostProcessorAdapter这样一个适配器,既可以在以下几个点进行扩展

EP1-》实例化-》EP2-》属性填充-》EP3-》执行Aware接口-》EP4-》初始化-》应用-》销毁

具体实现如下:
在这里插入图片描述
扩展点和对应的方法如下:

1.实例化前的扩展点EP1 => postProcessBeforeInstantiation

2.实例化后的扩展点EP2 => postProcessAfterInstantiation

3.初始化前的扩展点EP3 => postProcessBeforeInitialization

4.初始化后的扩展点EP4 => postProcessAfterInitialization

以上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值