最近突然身边很多小伙伴问我有没有spring bean生命周期的通俗移动的介绍
起初不太理解为什么,后来才想明白,哦对了,年底了,快开始跳槽季了,这不就是java八股文面试
的题目嘛,不得不说,国内真的很卷,之前有认识的外国友人,人家说面试根本不会问这些,基本就是
问问做过哪些项目,功能,模块就完事了,主要是试用期去衡量他的能力,好了闲话少说,我们开始
正式聊一聊spring bean 的生命周期,本文不涉及循环依赖以及三级缓存问题,如果需要的话,我可以后续有时间的时候单独写一篇介绍,本文只针对bean的生命周期,尽量用最简化的方式描述
其实我觉得大家是把主流程和分支流程搞一起了,网上大部分文章都是混在一起介绍的,比如创建实例createBeanInstance之前会执行
InstantiationAwareBeanPostProcessor的postProcessBeforeInitialization方法,
创建之后还会执行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法然后执行 InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法
其实这些大家不需要和主流程混在一起记忆,因为这些都是辅助分支流程,因为可能你定义多少实现类那就是多少辅助流程循环执行
其实真正的spring bean 生命周期大家只要记住是生成实例->填充属性->初始化->销毁就可以了
为了方便大家记忆,我特意画了一个流程图,主流程和辅助流程是分开的,一目了然,再结合我下面的demo,跑一下程序或者自己写一个验证一下就可以了,如图下:
目录结构
pom引用
org.springframework spring-context 5.2.5.RELEASE compile
创建空项目,引入spring-contenxt,为什么引入context,因为它包含了spring framework 基本的所有依赖pom
Application.java
/*** @Author alan.wang*/
public class Application {public static Integer index = 0;public static void main(String[] args){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Teacher teacher = context.getBean(Teacher.class);System.out.println("class:" + teacher.name());}
}
Teacher.java 以及TeacherImpl.java 实现类
TeacherImpl 实现了上图那些接口InitializingBean,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware,DisposableBean
/*** @Author alan.wang*/
public interface Teacher {String name();
}
/*** @Author alan.wang*/
@Service
public class TeacherImpl implements Teacher , InitializingBean, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware , DisposableBean {public String name() {return "teacher";}@PostConstructpublic void init(){System.out.println(++Application.index+" postConstruct");}public void afterPropertiesSet() throws Exception {System.out.println(++Application.index+" afterPropertiesSet");}public void setBeanName(String name) {System.out.println(++Application.index+" setBeanName");}public void setBeanClassLoader(ClassLoader classLoader) {System.out.println(++Application.index+" setBeanClassLoader");}public void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println(++Application.index+" setBeanFactory");}@Overridepublic void destroy() throws Exception {System.out.println(++Application.index+" destroy");}
}
PrintAwareBeanPostProcessor.java
PrintAwareBeanPostProcessor实现了InstantiationAwareBeanPostProcessor 接口主要是对类创建实例前和后的包装
这里就是单纯地输出,证明执行了
/*** @Author alan.wang*/
@Service
public class PrintAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {System.out.println(++Application.index+" InstantiationAwareBeanPostProcessor-postProcessBeforeInstantiation:"+beanName);return null;}public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {System.out.println(++Application.index+" InstantiationAwareBeanPostProcessor-postProcessAfterInstantiation:"+beanName);return true;}public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {System.out.println(++Application.index+ " InstantiationAwareBeanPostProcessor-postProcessProperties:"+beanName);return pvs;}
}
PrintMergedBeanDefinitionPostProcessor.java
PrintMergedBeanDefinitionPostProcessor
实现了MergedBeanDefinitionPostProcessor 接口,主要是对实例化后的bean进行自定义的mergec处理
这里仅仅是对方法进行输出
/*** @Author alan.wang*/
@Component
public class PrintMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {System.out.println(++Application.index+" MergedBeanDefinitionPostProcessor-postProcessMergedBeanDefinition:"+beanName);}public void resetBeanDefinition(String beanName) {System.out.println(++Application.index+" MergedBeanDefinitionPostProcessor-resetBeanDefinition:"+beanName);}
}
> ***PrintBeanPostProcessor.java
> PrintBeanPostProcessor实现了BeanPostProcessor接口 BeanPostProcessor实际上是根接口,InstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor都是它的子接口
> BeanPostProcessor 一般是对bean 初始化阶段的前后before 和after处理
> 这里也仅仅是方法输出***
/*** @Author alan.wang*/
@Service
public class PrintBeanPostProcessor implements BeanPostProcessor {public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(++Application.index+" BeanPostProcessor-postProcessBeforeInitialization:"+beanName);return bean;}public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(++Application.index+" BeanPostProcessor-postProcessAfterInitialization:"+beanName);return bean;}
}
首先来看下执行输出执行顺序结果
我们看到首先执行的是InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法
该方法是在创建bean的实例之前的,源码如下:
然后是创建bean实例
然后是填属性,也就是依赖注入
然后是MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
然后是InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法
然后是InstantiationAwareBeanPostProcessor的postProcessProperties方法
然后是BeanNameAware的setBeanName 方法 然后是BeanClassLoaderAware的setBeanClassLoader方法
然后是BeanFactoryAware的setBeanFactory 方法,他们可以看做是一体的
然后是BeanPostProcessor的postProcessBeforeInitialization方法
然后是@postConstruct注解的方法
然后是执行初始化函数
然后是InitializingBean的afterPropertiesSet方法
然後是BeanPostProcessor的postProcessAfterInitialization方法
然后是destory 相关,destory实际上demo不会触发,因为执行结束了主线程结束就关闭了,需要一个CloseEvent消息,需要添加addShutdownHook 这里暂时不做介绍
不要死记硬背,不要被辅助流程干扰,结合上述流程图去看源码,跑遍demo基本就了解了