Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,掌握这些可以加深对 Spring 的理解。
首先看下生命周期图:
再谈生命周期之前有一点需要先明确:
Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。
Bean实例化过程:
1.Spring启动,查找并加载需要被Spring管理的bean,利用反射进行Bean的实例化
2、将配置文件中配置的属性填充到刚刚创建的 bean 对象中。
3、如果Bean实现BeanNameAware接口,调用setBeanName()方法,传入Bean的名字
4、如果Bean实现BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
5.如果Bean实现BeanFactoryAware接口,Spring传递beanfactory给setBeanFactory方法。
6.如果Bean实现ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
7.如果Bean实现BeanPostProcessor前置处理接口,Spring就将调用他们的 postProcessBeforeInitialization()方法。
8.如果Bean实现InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
9.如果Bean实现BeanPostProcessor接口,Spring就将调用他们的 postProcessAfterInitialization()方法。我们所熟知的 AOP 就是在这里将 Adivce 逻辑织入到 bean 中的。
10.此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
11.如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。
BeanPostProcessor 是一个很有用的接口,通过实现接口我们就可以插手 bean 的实例化过程,为拓展提供了可能。我们所熟知的 AOP 就是在这里进行织如入,具体点说是在 postProcessAfterInitialization(Object bean, String beanName) 执行织入逻辑的。
1、查找实现了 PointcutAdvisor 类型的切面类,切面类包含了 Pointcut 和 Advice 实现类对象。
2、检查 Pointcut 中的表达式是否能匹配当前 bean 对象。
3、如果匹配到了,表明应该对此对象织入 Advice。
4、将 bean,bean class对象,bean实现的interface的数组,Advice对象传给代理工厂 ProxyFactory。代理工厂创建出 AopProxy 实现类,最后由 AopProxy 实现类创建 bean 的代理类,并将这个代理类返回。此时从 postProcessAfterInitialization(Object bean, String beanName) 返回的 bean 此时就不是原来的 bean 了,而是 bean 的代理类。原 bean 就这样被无感的替换掉了。
Spring AOP 生成代理类的逻辑是在 AbstractAutoProxyCreator 相关子类中实现的,比如 DefaultAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator 等。上面说了 BeanPostProcessor 为拓展留下了可能,这里 AbstractAutoProxyCreator 就将可能变为了现实。AbstractAutoProxyCreator 实现了 BeanPostProcessor接口,这样 AbstractAutoProxyCreator 可以在 bean 初始化时做一些事情。光继承这个接口还不够,继承这个接口只能获取 bean,要想让 AOP 生效,还需要拿到切面对象(包含 Pointcut 和 Advice)才行。所以 AbstractAutoProxyCreator 同时继承了 BeanFactoryAware 接口,通过实现该接口,AbstractAutoProxyCreator 子类就可拿到 BeanFactory,有了 BeanFactory,就可以获取 BeanFactory 中所有的切面对象了。有了目标对象 bean,所有的切面类,此时就可以为 bean 生成代理对象了。
在 bean 初始化时会经历几个阶段,首先可以使用注解 @PostConstruct, @PreDestroy 来在 bean 的创建和销毁阶段进行调用
@Component public class AnnotationBean { private final static Logger LOGGER = LoggerFactory.getLogger(AnnotationBean.class); @PostConstruct public void start(){ LOGGER.info("AnnotationBean start"); } @PreDestroy public void destroy(){ LOGGER.info("AnnotationBean destroy"); } }还可以实现 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"); } }以下是在 SpringBoot 中可以这样配置,如果是原始的基于 XML 也是可以使用;
@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"); } }Aware 接口可以用于在初始化 bean 时获得 Spring 中的一些对象,如获取 Spring 上下文等
BeanNameAware:注入当前bean对应beanName;BeanClassLoaderAware:注入加载当前bean的ClassLoader;BeanFactoryAware:注入当前BeanFactory容器的引用。 @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 接口,Spring 中所有 bean 在做初始化时都会调用该接口中的两个方法,可以用于对一些特殊的 bean 进行处理.
@Component public class SpringLifeCycleProcessor implements BeanPostProcessor { private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleProcessor.class); /** * 预初始化 初始化之前调用 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("annotationBean".equals(beanName)){ LOGGER.info("SpringLifeCycleProcessor start beanName={}",beanName); } return bean; } /** * 后初始化 bean 初始化完成调用 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("annotationBean".equals(beanName)){ LOGGER.info("SpringLifeCycleProcessor end beanName={}",beanName); } return bean; } }