专题系列分类:玩转SpringBoot2.x系列教程
开发工具:Spring Tool Suite (STS)
springboot版本:2.0.5.RELEASE
jdk版本:1.8.0_144
在阅读该博客前建议大家一定要把demo写下来 在自己的环境下,根据操作静下心来一步步看。阅读源码本身是一个比较费神的操作,建议大家一定要多看 看明白后自己在把大体思路捋一下。 因为springboot用的也是spirng 所以下面介绍主要是spirng 而不是springboot 特此说明。
我们知道spring可以为我们创建bean对象实例 和以及Bean 属性注入,但是如果我们想要在Bean自动装配完成后自定义操作怎么处理呢?我们需要BeanPostProcessor 接口来完成自定义操作处理。当你还不知道我在说什么的情况下,那就直接看下面的代码吧。
定义一个名称为IMyBean的接口其中有2个方法 一个获取自定义值getCustomValue 一个进行设置自定义值的方法 setCustomValue
package cn.lijunkui.customBean;
public interface IMyBean {
void setCustomValue(String v);
String getCustomValue();
}
创建名称为MyBean的实体类 并实现IMyBean 并通过@Component 直接声明该类为spirng的bean
package cn.lijunkui.customBean;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements IMyBean{
private String customValue;
@Override
public void setCustomValue(String customValue) {
this.customValue = customValue;
}
@Override
public String getCustomValue() {
return customValue;
}
}
创建实现BeanPostProcessor 的实现类完成对MyBean的初始化后自定义操作 如果在初始化MyBean 后customValue的值如果为空则将其设置为“defaultValue”
package cn.lijunkui.customBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
private Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof IMyBean) {
log.info("=======>postProcessAfterInitialization");
IMyBean mybean = (IMyBean) bean;
if (mybean.getCustomValue() == null) {
mybean.setCustomValue("defaultValue");
}
}
return bean;
}
}
通过在启动类中获取ConfigurableApplicationContext 获取MyBean测试customValue的值是否改变。(这里我们额外说一下Spirng中的bean都是通过BeanFactory进行管理的,在Spirng中默认使用的是DefaultListableBeanFactory 也就是BeanFactory的实现。 而下面代码中ConfigurableApplicationContext getBean 就是BeanFactory中的方法)
package cn.lijunkui;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import cn.lijunkui.customBean.MyBean;
@SpringBootApplication
public class PrincipleApplication {
private static Logger log=LoggerFactory.getLogger(PrincipleApplication.class);
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(PrincipleApplication.class, args);
MyBean mybean = run.getBean(MyBean.class);
log.info("getCustomValue:"+mybean.getCustomValue());
}
}
测试结果: 我们看到下图中加载的过程中进行了回调并且将customValue的值设置成了 defaultValue
为什么实现 BeanPostProcessor就可以进行bean初始化后的操作呢?想知道其中的原理我们就要去看看spring的源码了。
第一步在MyBeanPostProcessor postProcessAfterInitialization方法中打一个段断点 然后启动spirngboot项目
当断点走到 postProcessAfterInitialization 方法上事 如下图它的调用链就出来了,是不是很清晰。
根据上图调用链我们继续查看 AbstractAutowireCapableBeanFactory.initializeBean 方法 该方法中我们看到和BeanPostProcessor 有关的2个方法
applyBeanPostProcessorsBeforeInitialization 和applyBeanPostProcessorsBeforeInitialization 是不是感觉和BeanPostProcessor 相关,下面是initializeBean 具体逻辑实现
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @return the initialized bean instance (potentially wrapped)
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
applyBeanPostProcessorsBeforeInitialization 方法的具体实现逻辑如下
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
当我们看到Object current = processor.postProcessBeforeInitialization(result, beanName); 是不是知道了 这里会获取所有的BeanPostProcessor 然后调用postProcessBeforeInitialization
BeanPostProcessors 逻辑如下:
获取AbstractBeanFactory 中的 beanPostProcessors
/**
* Return the list of BeanPostProcessors that will get applied
* to beans created with this factory.
*/
public List getBeanPostProcessors() {
return this.beanPostProcessors;
}
applyBeanPostProcessorsAfterInitialization 逻辑和applyBeanPostProcessorsBeforeInitialization逻辑基本一直 代码如下
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
BeanPostProcessor 调用时序图如下:中间很多流程做了简化 画的是核心的逻辑。
还有一个问题就是我们的 BeanPostProcessor 集合是在什么时添加的?关闭到我们的springboot服务
还是下图的断点 在次一debug方式启动
通过调用的链路往下找 知道找到 AbstractApplicationContext 中的refresh() 方法中的 registerBeanPostProcessors(beanFactory)
通过PostProcessorRegistrationDelegate.registerBeanPostProcessors 将 放入到beanFactory 中
registerBeanPostProcessors 方法中获取到所有的BeanPostProcessor 然后放入集合中
然后再将BeanPostProcessor集合 放入到 beanFactory 中
PostProcessorRegistrationDelegate registerBeanPostProcessors 具体源码逻辑如下
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
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 priorityOrderedPostProcessors = new ArrayList<>();
List internalPostProcessors = new ArrayList<>();
List orderedPostProcessorNames = new ArrayList<>();
List 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);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List orderedPostProcessors = new ArrayList<>();
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 nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
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));
}
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
通过下图了解springboot启动后如何执行到 AbstractApplicationContext refresh 方法流程。
大致流程如下:
在 Spring 初始化完成后会回调 GenericApplicationContext 中的 refresh 方法,然后再通过AbstractApplicationContext 抽象类中的 refresh 来实现。
在refresh 方法中registerBeanPostProcessors 调用了 PostProcessorRegistrationDelegate,将 BeanFactory 作为参数传入,在registerBeanPostProcessors中获取所有的BeanPostProcessor获取完所有实现类后,根据实现类上的顺序进行排序,然后将排序好的集合对象调用BeanFactory.addBeanPostProcessor 注册到 BeanFactory 中。
这样在 AbstractAutowireCapableBeanFactory 中就可以从它的父类 AbstractBeanFactory 中直接获取到 BeanPostProcessor 集合对象了,也就是上面调用的 getBeanPostProcessors() 方法。