写在前面
本文旨在分析BeanPostProcessor
的加载流程和调用流程,并通过BeanPostProcessor
同时分析一下ApplicationContextAware
这个常用的获取Spring的ApplicationContext
的接口,学习本文需要对SpringIOC有一定的了解,不了解的请看SpringIOC源码解析或者自行了解
一. BeanPostProcessor简介
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口,当一个BeanPostProcessor的实现类注册到Spring IOC容器后,对于该Spring IOC容器所创建的每个bean实例在初始化方法调用前,将会调用BeanPostProcessor
中的postProcessBeforeInitialization
方法,而在bean实例初始化方法调用完成后,则会调用BeanPostProcessor
中的postProcessAfterInitialization
方法。
二. 源码
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;
}
}
三. 通过例子分析
applicationIoc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<bean id="testBeanPostProcessor" class="com.jingchuan.beanPostProcessor.TestBeanPostProcessor"/>
<bean id="fruits" class="com.jingchuan.model.Fruits">
<property name="name" value="banana"></property>
</bean>
</beans>
Fruits 类
public class Fruits {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
实现了BeanPostProcessor的TestBeanPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class TestBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("TestBeanPostProcessor -- postProcessBeforeInitialization ---- " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("TestBeanPostProcessor -- postProcessAfterInitialization ---- " + beanName);
return bean;
}
}
测试类
import com.jingchuan.model.Fruits;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestIoc {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationIoc.xml");
Fruits fruits = (Fruits) context.getBean("fruits");
System.out.println(fruits.getName());
}
}
四. 源码分析
首先我们知道在上面例子中配置的两个Bean:testBeanPostProcessor
和fruits
在IOC加载的时候都会被注册到Spring容器中,这里不了解的同学可以去看我的这篇SpringIOC源码解析。
那么我们来到IOC加载源码分析中,首先IOC会加载注册Bean的定义BeanDefinition,那么配置的这两个Bean毋庸置疑肯定会被注册进去,这一步没啥好说的就直接略过了。接着来到org.springframework.context.support.AbstractApplicationContext#refresh
方法的registerBeanPostProcessors(beanFactory);
,这一步是注册拦截Bean创建的处理器的,其实就是注册所有的BeanPostProcessor
的,我们进入源码看:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
// 这一步是在已经注册的Bean定义BeanDefinition中寻找实现了BeanPostProcessor的Bean
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 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));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 创建多个List用来对筛选出来的所有BeanPostProcessor进行分组
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
// 我们例子中的TestBeanPostProcessor会被加入nonOrderedPostProcessorNames
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
// 循环nonOrderedPostProcessorNames里面存储的所有BeanPostProcessor Bean的名称
for (String ppName : nonOrderedPostProcessorNames) {
// 依次初始化实现了BeanPostProcessor的Bean 这就是IOC的getBean实例化
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 把实例化完成的所有BeanPostProcessor实例进行注册 其实就是保存到List中
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
在上面这段代码中,首先从工厂里面获取已经注册好的BeanDefinition中实现了BeanPostProcessor
的Bean,里面的代码就不跟进去分析了,我们这里只需要知道是筛选出BeanPostProcessor
就行,然后把筛选出来的BeanPostProcessor
循环进行实例化,最后进行注册,实际就是添加到:org.springframework.beans.factory.support.AbstractBeanFactory#beanPostProcessors
,这样我们实现了BeanPostProcessor
的TestBeanPostProcessor
就被注册进去了。
然后回到org.springframework.context.support.AbstractApplicationContext#refresh
方法的finishBeanFactoryInitialization(beanFactory);
实例化所有非懒加载的单例bean,在我们的例子中,就是实例化Fruits
这个Bean了,那么我们已经知道了BeanPostProcessor
是Spring IOC容器所创建的每个bean实例在初始化方法调用前后进行拦截处理,那么我们直接来到Fruits
初始化前后进行分析,多余的就不再一步一步跟进了,直接来到:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化之前的BeanPostProcessor拦截处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//初始化Bean
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 初始化之后的BeanPostProcessor拦截处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
在这个方法中就可以看到Bean实例化前后会进行拦截并根据org.springframework.beans.factory.support.AbstractBeanFactory#beanPostProcessors
中注册的依次进行调用,初始化前是postProcessBeforeInitialization
,初始化之后是postProcessAfterInitialization
,那么在我们的例子中,Fruits
对象在初始化前后就分别会调用到TestBeanPostProcessor
的postProcessBeforeInitialization
和postProcessAfterInitialization
。
以上就是Spring的BeanPostProcessor
从注册到拦截调用的全过程。
五. 通过BeanPostProcessor来看ApplicationContextAware
日常开发我们经常会静态代码的方式从Spring容器中获取某个Bean,一般就是叫做SpringContextUtils
的工具类,实现了ApplicationContextAware
接口并实现其setApplicationContext
从而获取到Spring的ApplicationContext
容器,然后从容器中获取Bean对象等等;那么为什么实现这个接口方法就能获取到容器呢?
接下来开始分析:
国际惯例先来个例子:
实现ApplicationContextAware
接口的TestApplicationContextAware
类
import com.jingchuan.model.Fruits;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class TestApplicationContextAware implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Fruits fruits = (Fruits) applicationContext.getBean("fruits");
System.out.println(fruits.getName());
}
}
applicationIoc.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<bean id="testApplicationContextAware" class="com.jingchuan.config.TestApplicationContextAware"/>
<bean id="fruits" class="com.jingchuan.model.Fruits">
<property name="name" value="banana"></property>
</bean>
</beans>
Fruits 类
public class Fruits {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试类:
import com.jingchuan.model.Fruits;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestIoc {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationIoc.xml");
Fruits fruits = (Fruits) context.getBean("fruits");
System.out.println(fruits.getName());
}
}
接下来进入源码:
首先来到org.springframework.context.support.AbstractApplicationContext#refresh
的prepareBeanFactory(beanFactory);
这一步:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 添加一个ApplicationContextAwareProcessor到beanPostProcessors 这个就是上面分析的beanPostProcessor存放的集合
// 所以Spring其实默认的在启动过程中注册了一个ApplicationContextAwareProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
可以看到Spring容器在启动的过程中默认的添加一个BeanPostProcessor
:ApplicationContextAwareProcessor
,这个ApplicationContextAwareProcessor
实现自BeanPostProcessor
,那到这里大家就应该明白这个会在Bean初始化的前后被调用了。
到这里我们知道了Spring默认注册了一个ApplicationContextAwareProcessor
。
然后来到TestApplicationContextAware
这个我们自定义的Bean的初始化过程中,因为上面注册了一个ApplicationContextAwareProcessor
,而这个类有一个方法:postProcessBeforeInitialization
实现自BeanPostProcessor
,那么肯定就是在Bean初始化之前会调用这个方法。那我们就直接来看这个方法的源码:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
可以看到一进来就一个if
判断,那么多个条件中是不是有一个:bean instanceof ApplicationContextAware
,那么这个ApplicationContextAware
就是我们的例子中TestApplicationContextAware
实现的接口,那么初始化这个Bean的时候就会通过这个if
继续往下走,然后回来到:invokeAwareInterfaces(bean);
这个方法:
private void invokeAwareInterfaces(Object bean) {
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 ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
// 本例中的TestApplicationContextAware就会进入下面这个if
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
这个方法就是进行instanceof
判断,那么我们这个TestApplicationContextAware
实现了ApplicationContextAware
自然就会进入最后一个if
判断,那自然也就进入了我们的TestApplicationContextAware
的setApplicationContext
方法里面,这个入参就是Spring容器的applicationContext
,那么我们自定义的工具类就可以拿到Spring容器上下文引用了。
这就是实现ApplicationContextAware
可以获取到Spring容器上下文引用的原因了。