基础
如果使用过Spring,写过项目,那么一定了解IOC容器,Bean校验,@Autowired依赖注入这些,其实内部很多实现,都是通过BeanPostProcessor来实现
BeanPostProcessor 作用:
初始化Bean前后做一些赋值,解析处理相关操作
BeanPostProcessor接口
public interface BeanPostProcessor {
/**
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
我们只需要实现该接口,标注@Bean注入容器,容器在创建该Bean实例后,调用对应的BeanPostProcessor进行相关处理
对应的实现类,这里标注了一部分常用的
我们这里以实际案例为切入点,进行切入分析
ApplicationContextAwareProcessor
我们开发中,特别是多模块开发中,对于有些模块不需要Spring,因此往往不会给这个模块导入Spring依赖,该模块也就无法获取IOC容器。
但是有时,我们又需要IOC容器,获取其中的Bean,Environment。往往定义一个工具类模块,定义一个Bean实现ApplicationContextAware接口,往其中注入IOC容器,最后通过静态方法,其它模块也可以获取IOC容器了
ApplicationContextAwareProcessor源码
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
测试
获取IOC容器的类
public class IOCUtil implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}
主配置类
@Configuration
public class MainConfig {
@Bean
public IOCUtil iocUtil(){
return new IOCUtil();
}
}
测试方法和结果
@Test
public void test02(){
AnnotationConfigApplicationContext applicationContext = new
AnnotationConfigApplicationContext(MainConfig.class);
IOCUtil iocUtil = applicationContext.getBean(IOCUtil.class);
System.out.println(iocUtil.getApplicationContext());
System.out.println(applicationContext);
applicationContext.close();
}
可以看到通过实现ApplicationContextAware,然后将Bean放入IOC容器,IOC容器创建Bean实例后,自动通过对应方法将IOC容器传送过来保存。此时两个IOC容器对象一样,说明是同一个
那么怎么实现的呢???
1、创建容器
2、调用reFresh,刷新容器
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
.........省略部分不重要源码
# 为上下文准备BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
# 调用BeanPostProcessor,扫描组件,生成BeanDefinition,
invokeBeanFactoryPostProcessors(beanFactory);
## 注册准备BeanPostProcessors默认七个
registerBeanPostProcessors(beanFactory);
## 通过BeanDefinition创建Bean实例,通过注册的BeanPostProcessor对Bean init,属性赋值,进行前后处理
finishBeanFactoryInitialization(beanFactory);
}
}
}
BeanDefinitionMap
BeanPostProcessors默认七个
走到这里BeanPostProcessors已经全部创建完毕,只等InitBean时候进行调用
3、finishBeanFactoryInitialization(beanFactory); 生成实例,初始化Bean示例
通过BeanDefinition创建Bean实例,通过注册的BeanPostProcessor对Bean init,属性赋值,进行前后处理
finishBeanFactoryInitialization(beanFactory);
生成实例流程(默认没有,会创建)
doGetBean中的
bean默认不存在,通过BeanDefinition,会创建的
此时Bean已经创建完成(底层是通过反射+动态代理实现,有兴趣可以自行查看源码)populateBean为bean赋属性值,
Bean创建完成并属性赋值之后,对Bean进行初始化
显然我们IOCUtil实现ApplicationContextAware接口
可惜的是我们并没有实现BeanFactoryAware这样的接口,因此无法调用,SetBeanFactoryAware的方法,无法获取BeanFactory容器
调用BeanPostProcessorsBeforeInitialization
获取默认注册过的BeanPostProcessor,默认七个
ApplicationContextAwareProcessor
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
找到Bean实现的Aware接口
由于我们实现ApplicationContextAware,向上转型,为Bean设置ApplicationContext
最终走到了我们自定义的Bean中,保存applicationContext,因此Bean获取到了applicationContext
注意:如果我们想获取ApplicationContext,Beanfactory,Environment等等,可以实现这些Aware接口,在initialBean时候,通过XXXAwareProcessor(BeanPostProcessor)进行设值保存
PostProcessorBeforeInitialization走完后,会走 initBean
initBean走完后,会走PostProcessorAfterInitialization