由于前面有一篇文章解释了spring如何解决bean循环依赖的问题,里面涉及了SmartInstantiationAwareBeanPostProcessor的切面,这次干脆把BeanPostProcessor和InstantiationAwareBeanPostProcessor一起讲了,也好巩固下知识点
基础知识:
Bean创建过程中的“实例化”与“初始化”名词
1、实例化(Instantiation): 要生成对象, 对象还未生成.
2、初始化(Initialization): 对象已经生成.,赋值操作。
演示:
我们用一个简单的Spring Bean来演示一下Spring Bean的生命周期。
1、首先是一个简单的Spring Bean,调用Bean自身的方法和Bean级生命周期接口方法,为了方便演示,它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,同时有2个方法,对应配置文件中的init-method和destroy-method。如下:
package springBeanTest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* @author qsk
*/
public class Person implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean {
private String name;
private String address;
private int phone;
private BeanFactory beanFactory;
private String beanName;
public Person() {
System.out.println("【构造器】调用Person的构造器实例化");
}
// 这是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out
.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
this.beanFactory = arg0;
}
// 这是BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
this.beanName = arg0;
}
// 这是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out
.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
}
// 这是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
}
// 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
}
// 通过<bean>的destroy-method属性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
}
}
主要流程为:
实例化 -> 属性赋值 -> 初始化 -> 销毁
主要逻辑都在doCreate()方法中,逻辑很清晰,就是顺序调用以下三个方法,这三个方法与三个生命周期阶段一一对应,非常重要,在后续扩展接口分析中也会涉及。
createBeanInstance() -> 实例化
populateBean() -> 属性赋值
initializeBean() -> 初始化
而beanpostProcessor和InstantiationAwareBeanPostProcessor作用于实例化阶段的前后,BeanPostProcessor作用于初始化阶段的前后,如下
BeanPostProcessor
BeanPostProcessor是spring非常重要的拓展接口,例如aop通过拓展接口生产代理bean等。接口有两个方法:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
ApplicationContext类型的容器会自动发现和注册该类型的bean,通过BeanPostProcessor可以对bean进行定制化,接口作用域是所有bean创建。
1、postProcessBeforeInitialization触发时机在bean实例化(Instantiation)之后,所有初始化(Initialization)动作(包括 InitializingBean#afterPrpertiesSet() 和 定制化init-method())以前。
2、postProcessAfterInitialization触发时机在bean实例化(Instantiation)之后,所有初始化(Initialization)动作(包括 InitializingBean#afterPrpertiesSet() 和 定制化init-method())以后。同时还会在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 和 FactoryBean(bean工厂)获得bean时候调用
BeanPostProcessor 的Demo
由于ApplicationContext可以自动发现并注册BeanPostProcessor,如下使用ApplicationContext类型容器实现一个简单demo。
1 public class BeanPostProcessorTest {
2
3 private ApplicationContext applicationContext ;
4
5 @Before
6 public void beforeApplicationContext(){
7 /**
8 * ApplicationContext 自动注册 BeanPostProcessor
9 * 不需要手动注册
10 * */
11 applicationContext = new ClassPathXmlApplicationContext("ioc-beanPostProcessor.xml") ;
12 }
13
14 @Test
15 public void test(){
16 Bean bean = applicationContext.getBean("bean", Bean.class) ;
17 System.out.println(bean);
18 }
19
20 @After
21 public void after(){
22 ((ClassPathXmlApplicationContext)applicationContext).close();
23 }
24 }
BeanPostProcessorTest.java
1 public class Bean {
2
3 public Bean(){
4
5 }
6
7 public Bean(String name){
8 System.out.println("构造函数被调用啦");
9 this.name = name ;
10 }
11
12 private String name ;
13
14
15 public String getName() {
16 return name;
17 }
18
19 public void setName(String name) {
20 this.name = name;
21 }
22
23 @Override
24 public String toString() {
25 return "Bean{" +
26 "name='" + name + '\'' +
27 '}';
28 }
29 }
Bean.java
1 public class LogicBeanPostProcessor implements BeanPostProcessor {
2
3 @Nullable
4 @Override
5 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
6 System.out.println("LogicBeanPostProcessor.postProcessAfterInitialization 执行啦 beanName = " + beanName);
7 return bean;
8 }
9
10 @Nullable
11 @Override
12 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
13 System.out.println("LogicBeanPostProcessor.postProcessBeforeInitialization 执行啦 beanName = " + beanName);
14 return bean;
15 }
16 }
LogicBeanPostProcessor.java
结果:
构造函数被调用啦
LogicBeanPostProcessor.postProcessBeforeInitialization 执行啦 beanName = bean
LogicBeanPostProcessor.postProcessAfterInitialization 执行啦 beanName = bean
Bean{name=‘zhouxiaoxing’}
BeanPostProcessor源码分析:注册时机和触发点
1、注册BeanPostProcessor
在AbstractApplicationContext容器启动的refresh()会注册BeanPostProcessor,源码如下:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册BeanPostProcessor 在bean创建的时候进行拦截
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
......
/**
* Instantiate and invoke all registered BeanPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before any instantiation of application beans.
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
跟进PostProcessorRegistrationDelegate.registerBeanPostProcessors
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
/**
* 此时bean的定义加载已经完成,但是还没有实例化。 获得所有BeanPostProcessor bean对应的beanName
*/
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
/**
* 注册日志BeanPostProcessor, 检测注册的bean是否为spring基础服务类并打印日志
*/
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
/**
* 当有注册多个BeanPostProcessor接口时会按顺序进行,即 实现PriorityOrdered->实现Ordered->普通类型接口->内部系统MergedBeanDefinitionPostProcessor
*/
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List