写在前面
本文旨在分析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) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
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 {
nonOrderedPostProcessorNames.add(ppName);
}
}
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
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);
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
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()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
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()) {
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) {
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
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.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
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());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
这个方法就是进行instanceof 判断,那么我们这个TestApplicationContextAware 实现了ApplicationContextAware 自然就会进入最后一个if 判断,那自然也就进入了我们的TestApplicationContextAware 的setApplicationContext 方法里面,这个入参就是Spring容器的applicationContext ,那么我们自定义的工具类就可以拿到Spring容器上下文引用了。 这就是实现ApplicationContextAware 可以获取到Spring容器上下文引用的原因了。
|