BeanFactoryPostProcessor->postProcessBeanFactory() ;
Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它。同时可以定义BeanFactoryPostProcessor,通过设置’order’属性来确定各个BeanFactoryPostProcessor执行顺序。
InstantiationAwareBeanPostProcessor ->postProcessPropertyValues()
属性注入(setter)
BeanNameAware ->setBeanName()
BeanFactoryAware->setBeanFactory()
ApplicationContextAware->setApplicationContext()
BeanPostProcessor ->postProcessBeforeInitialization()
InitializingBean->afterPropertiesSet()
init-method属性
BeanPostProcessor->postProcessAfterInitialization()
DiposibleBean->destory()
destroy-method属性
容器刷新的过程可以细分为如下几个步骤
Spring应用上下文启动准备阶段
AbstractApplicationContext#prepareRefresh
BeanFactory创建阶段
AbstractApplicationContext#obtainFreshBeanFactory
刷新Spring应用上下文底层BeanFactory(refreshBeanFactory)
BeanFactory准备阶段
AbstractApplicationContext#prepareBeanFactory
BeanFactory后置处理阶段
如果想对BeanFactory进行扩展,可以通过如下2种方式
AbstractApplicationContext#invokeBeanFactoryPostProcessors 方法就是用来处理BeanFactoryPostProcessor接口的,调用的次序比较复杂,BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子类,调用顺序总结如下
BeanDefinitionRegistryPostProcessor是用来自定义bean的。
注册BeanPostProcessor(ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor)
注册LoadTimeWeaverAwareProcessor对象
前面说过在容器初始化的过程中,往容器中注入了一个BeanFactoryPostProcessor接口的实现类即ConfigurationClassPostProcessor。
这是一个非常重要的BeanFactoryPostProcessor,通过@Bean、@Component、@ComponentScan、@Import、@ImportResource注入Bean的方式都由这个类来处理,对这些注解的实现感兴趣的小伙伴可以看一下这个类的源码
回调BeanFactoryPostProcessor接口的相关方法就搞这么多排序规则,有必要吗?
有必要,一方面是提高可扩展性,另外一方面是有些实现类的调用优先级必须要高一点,不然会有问题,我后面用例子演示
BeanFactory注册BeanPostProcessor阶段
此时注册到容器中的BeanPostProcessor有6个,这6个BeanPostProcessor在Spring Bean的生命周期中起着重要的作用,这个注册时机会影响后面调用的时机,所以搞优先级很有必要
1.bean对象的实例化
2.封装属性,也就是设置properties中的属性值
3.如果bean实现了BeanNameAware,则执行setBeanName方法,也就是bean中的id值
4.如果实现BeanFactoryAware或者ApplicationContextAware ,需要设置setBeanFactory或者上下文对象setApplicationContext
5.如果存在类实现BeanPostProcessor后处理bean,执行postProcessBeforeInitialization,可以在初始化之前执行一些方法
6.如果bean实现了InitializingBean,则执行afterPropertiesSet,执行属性设置之后的操作
7.调用执行指定的初始化方法
8.如果存在类实现BeanPostProcessor则执行postProcessAfterInitialization,执行初始化之后的操作
9.执行自身的业务方法
10.如果bean实现了DisposableBean,则执行spring的的销毁方法
11.调用执行自定义的销毁方法。
第五步和第八步可以结合aop,在初始化执行之前或者执行之后执行一些操作。
以上就是springbean的完整生命周期.
public class Man implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean,
BeanPostProcessor {
private String name;
public Man() {
System.out.println("1 实例化");
}
public void setName(String name) {
System.out.println("2 设置属性");
this.name = name;
}
public void setUp() {
System.out.println("7 执行自己配置的初始化方法");
}
public void run() {
System.out.println("9 执行自身的业务方法");
}
@Override
public void destroy() throws Exception {
System.out.println("10 执行spring的销毁方法");
}
public void selfDefineDestroy() {
System.out.println("11 执行自己配置的销毁方法");
}
public void setBeanName(String s) {
System.out.println("3 设置bean的名称也就是spring容器中的名称,也就是id值" + name);
}
public void afterPropertiesSet() throws Exception {
System.out.println("6 属性设置后执行的方法");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("4 设置ApplicationContext");
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("5 属性设置后执行的方法postProcessBeforeInitialization");
return null;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("8 属性设置后执行的方法postProcessAfterInitialization");
return null;
}
}
applicationContext.xml中的配置
测试
@Test
public void beanlifeTest(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
Man man=(Man)context.getBean("man");
man.run();
context.close();
}
结果
1 实例化
2 设置属性
3 设置bean的名称也就是spring容器中的名称,也就是id值zhangsan
4 设置ApplicationContext
6 属性设置后执行的方法
7 执行自己配置的初始化方法
9 执行自身的业务方法
10 执行spring的销毁方法
11 执行自己配置的销毁方法
前言
这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了《Spring in action》这本书,书上有对Bean声明周期的大致解释,但是没有代码分析,所以就自己上网寻找资料,一定要把这个Bean生命周期弄明白!
一、Bean 的完整生命周期
在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。
相比之下,Spring管理Bean的生命周期就复杂多了,正确理解Bean 的生命周期非常重要,因为Spring对Bean的管理可扩展性非常强,下面展示了一个Bean的构造过程
Bean 的生命周期
如上图所示,Bean 的生命周期还是比较复杂的,下面来对上图每一个步骤做文字描述:
上面是Spring 中Bean的核心接口和生命周期,面试回答上述过程已经足够了。但是翻阅JavaDoc文档发现除了以上接口外,还有另外的初始化过程涉及的接口:摘自org.springframework.beans.factory.BeanFactory, 全部相关接口如下,上述已有的就不用着重标注,把额外的相关接口着重标注下
Bean 完整的生命周期
文字解释如下:
————————————初始化————————————
Bean 的生命周期验证
为了验证Bean生命周期的过程,有两种形式:一种是为面试而准备的,一种是为了解全过程而准备的,下面来看代码:
Book.class
public class Book implements BeanNameAware, BeanFactoryAware,
ApplicationContextAware, InitializingBean, DisposableBean {
private String bookName;
public Book(){
System.out.println("1 Book Initializing ");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("4 Book.setBeanFactory invoke");
}
public void setBeanName(String name) {
System.out.println("3 Book.setBeanName invoke");
}
public void destroy() throws Exception {
System.out.println("10 Book.destory invoke");
}
public void afterPropertiesSet() throws Exception {
System.out.println("7 Book.afterPropertiesSet invoke");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("5 Book.setApplicationContext invoke");
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
System.out.println("2 setBookName: Book name has set.");
}
public void myPostConstruct(){
System.out.println("8 Book.myPostConstruct invoke");
}
// 自定义初始化方法
@PostConstruct
public void springPostConstruct(){
System.out.println("@PostConstruct");
}
public void myPreDestory(){
System.out.println("11 Book.myPreDestory invoke");
System.out.println("---------------destroy-----------------");
}
// 自定义销毁方法
@PreDestroy
public void springPreDestory(){
System.out.println("@PreDestory");
}
@Override
protected void finalize() throws Throwable {
System.out.println("------inside finalize-----");
}
}
自定义实现BeanPostProcessor 的MyBeanPostProcessor:
public class MyBeanPostProcessor implements BeanPostProcessor {
// 容器加载的时候会加载一些其他的bean,会调用初始化前和初始化后方法
// 这次只关注book(bean)的生命周期
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Book){
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Book){
System.out.println("MyBeanPostProcessor.postProcessAfterInitialization");
}
return bean;
}
}
在resources 目录下新建Bean-Lifecycle.xml
做一个启动类的测试,新建SpringBeanLifecycleApplication
public class SpringBeanLifecycleApplication {
public static void main(String[] args) throws InterruptedException {
// 为面试而准备的Bean生命周期加载过程
ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
Book book = (Book)context.getBean("book");
System.out.println("Book name = " + book.getBookName());
((ClassPathXmlApplicationContext) context).destroy();
}
}
启动测试,输出结果如下:
1 Book Initializing
2 setBookName: Book name has set.
3 Book.setBeanName invoke
4 Book.setBeanFactory invoke
5 Book.setApplicationContext invoke
6 MyBeanPostProcessor.postProcessBeforeInitialization
7 Book.afterPropertiesSet invoke
8 Book.myPostConstruct invoke
9 MyBeanPostProcessor.postProcessAfterInitialization
Book name = thingking in java
10 Book.destory invoke
11 Book.myPreDestory invoke
---------------destroy-----------------
为了验证Bean完整的生命周期,需要新建一个SubBookClass 继承Book类
public class SubBookClass extends Book implements BeanClassLoaderAware,
EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,
ApplicationEventPublisherAware,MessageSourceAware{
private String bookSystem;
public String getBookSystem() {
return bookSystem;
}
public void setBookSystem(String bookSystem) {
System.out.println("设置BookSystem 的属性值");
this.bookSystem = bookSystem;
}
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("SubBookClass.setBeanClassLoader() 方法被调用了");
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("SubBookClass.setApplicationEventPublisher() 方法被调用了");
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println("SubBookClass.setEmbeddedValueResolver() 方法被调用了");
}
public void setEnvironment(Environment environment) {
System.out.println("SubBookClass.setEnvironment() 方法被调用了");
}
public void setMessageSource(MessageSource messageSource) {
System.out.println("SubBookClass.setMessageSource() 方法被调用了");
}
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("SubBookClass.setResourceLoader() 方法被调用了");
}
}
上述SubBookClass类与Book是互补关系。
新建一个SubBean-Lifecycle.xml,注入SubBookClass
完整的SpringBeanLifecycleApplication 如下:
public class SpringBeanLifecycleApplication {
public static void main(String[] args) throws InterruptedException {
// 为面试而准备的Bean生命周期加载过程
ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
Book book = (Book)context.getBean("book");
System.out.println("Book name = " + book.getBookName());
((ClassPathXmlApplicationContext) context).destroy();
// 完整的加载过程,当然了解的越多越好
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SubBean-Lifecycle.xml");
SubBookClass subBookClass = (SubBookClass) applicationContext.getBean("bookClass");
System.out.println("BookSystemName = " + subBookClass.getBookSystem());
((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();
}
}
输出完整的结果:
Book Initializing
setBookName: Book name has set.
Book.setBeanName invoke
Book.setBeanFactory invoke
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
@PostConstruct
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
Book name = thingking in java
@PreDestory
Book.destory invoke
Book.myPreDestory invoke
---------------destroy-----------------
Book Initializing
设置BookSystem 的属性值
Book.setBeanName invoke
SubBookClass.setBeanClassLoader() 方法被调用了
Book.setBeanFactory invoke
SubBookClass.setEnvironment() 方法被调用了
SubBookClass.setEmbeddedValueResolver() 方法被调用了
SubBookClass.setResourceLoader() 方法被调用了
SubBookClass.setApplicationEventPublisher() 方法被调用了
SubBookClass.setMessageSource() 方法被调用了
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
BookSystemName = Java System
Book.destory invoke
Book.myPreDestory invoke
---------------destroy-----------------
Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
就是穿插在spring bean 初始化三个步骤的中间,具体的流程见下面。黄色为主线,同颜色的表示同一个对象
以下组要通过分析spring ioc源码的方式让大家理解spring bean的生命周期,源码分析过程只保留主线,一些不相关或者不重要的代码都省去。建议大家按照这个主线自已单步调试一下。
1. 加载bean配置文件
ApplicationContext factory = new ClassPathXmlApplicationContext("application-context.xml");
ClassPathXmlApplicationContext 构造函数内部主要就调用了一个方法-refresh方法。refresh方法就包含了spring ioc的全部流程。下面我们详细的分析
2. refresh()方法
public void refresh() throws BeansException, IllegalStateException {
// 设置一些环境变量、创建Environment,准备工作
prepareRefresh();
//创建beanFactory,加载BeanDefinition带beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//beanFactory设置一些必要的信息
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
//调用实现了BeanFactoryPostProcessor接口的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(beanFactory);
//注册实现BeanPostProcessor接口的bean,相当于bean的拦截器
registerBeanPostProcessors(beanFactory);
//国际化相关处理
initMessageSource();
//初始化容器的广播时间
initApplicationEventMulticaster();
onRefresh();
// 注册listeners beans
registerListeners();
// 实例bean,bean的生命周期大部分都在这个方法中
finishBeanFactoryInitialization(beanFactory);
// 发布finish通知, 注册bean的生命周期bean
finishRefresh();
} catch (BeansException ex) {
destroyBeans();
cancelRefresh(ex);
}
// 清空bean定义的一些元数据信息
resetCommonCaches();
}
2.1 prepareRefresh()方法
protected void prepareRefresh() {
/*
其实这个方法里面什么也没有做,但是可以重写改方法,设置一些环境变量。比如WebApplicationContext的实现类中AbstractRefreshableWebApplicationContext中就设置了servlet的一些初始变量
*/
initPropertySources();
/*
验证设置的环境变量是不是正确,有没有包含空值
*/
getEnvironment().validateRequiredProperties();
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2.2 obtainFreshBeanFactory()方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
return beanFactory;
}
2.2.1 refreshBeanFactory() 方法
@Override
protected final void refreshBeanFactory() throws BeansException {
// 创建BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
// 从xml文件或者注解加载BeanDefinition,存到DefaultListableBeanFactory的beanDefinitionMap字段
loadBeanDefinitions(beanFactory);
}
2.3 prepareBeanFactory()方法
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//设置classLoader
beanFactory.setBeanClassLoader(getClassLoader());
//el表达式支持
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 添加BeanPostProcessor, 不知道干嘛用的
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
//下面三个bean主要是系统的一些变量设置等等
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment())
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties())
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
2.4 invokeBeanFactoryPostProcessors()方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
/*
这个方法里面的代码比较长,总的来说就是调用实现了BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor接口的中的方法。在调用的时候按照接口是否实现PriorityOrdered, Ordered, 和其余的顺序调用。
1、如果需要在修改添加等对BeanDefinition的操作的话,实现BeanDefinitionRegistryPostProcessor接口
2、如果统计bean的一些信息,修改bean在配置BeanDefinition中的属性值等,实现BeanFactoryPostProcessor接口
*/
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
2.5 registerBeanPostProcessors()方法
与BeanFactoryPostProcessors类似,按一定的顺序注册实现BeanPostProcessor的接口
2.6 finishBeanFactoryInitialization()方法
// 实例化剩余的非lazy的bean,核心的代码都在这里面
beanFactory.preInstantiateSingletons()
2.6.1 preInstantiateSingletons() 方法
public void preInstantiateSingletons() throws BeansException {
List beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
//如果bean有父类,那么这个bean是可以合并的,需要把父类的相关信息比如属性和子类的合并。
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是FactoryBean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
2.6.1.1 getSingleton(String beanName, ObjectFactory> singletonFactory)方法
preInstantiateSingletons 会调用getBean(), getBean() 会调用doGetBean(),doGetBean()会调用getSingleton(),这是一个重要的方法,需要提出分析一下
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 如果singletonObject中没有创建好bean,就调用getObject方法。singletonFactory是函数接口,对应下面的createBean方法
singletonObject = singletonFactory.getObject();
}
addSingleton(beanName, singletonObject);
2.6.1.1.1 createBean()
createBean(){
// Give BeanPostProcessors a chance to return a proxy instead of the target
//在bean执行构造函数之前,给最后一个机会去执行一些操作,需要bean实现InstantiationAwareBeanPostProcessorAdapter接口
Object bean = bean instance.resolveBeforeInstantiation(beanName, mbdToUse);
//创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
2.6.1.1.1.1 doCreateBean()
//填充bean的属性,并且允许在设置bean属性值之前做一些操作,比如修改属性值
populateBean(beanName, mbd, instanceWrapper);
/*
1、bean感知,调用setBeanName和setBeanFactory接口
2、执行init-method方法之前执行一些处理工作,对应的方法是postProcessBeforeInitialization
3、调用InitializingBean.afterPropertiesSet()方法
4、调用init-method方法
5、执行BeanPostProcessor的postProcessAfterInitialization方法
6、执行InstantiationAwareBeanPostProcessorAdapter的postProcessAfterInitialization方法
*/
exposedObject = initializeBean(beanName, exposedObject, mbd);
//获取bean
Object earlySingletonReference = getSingleton(beanName, false);
//注册bean的DisposableBean(销毁使用)
registerDisposableBeanIfNecessary(beanName, bean, mbd);
```