玩转SpringBoot 2.x 解析BeanPostProcessor原理篇

专题系列分类:玩转SpringBoot2.x系列教程

1 demo 版本说明

开发工具:Spring Tool Suite (STS)

springboot版本:2.0.5.RELEASE

jdk版本:1.8.0_144

在阅读该博客前建议大家一定要把demo写下来 在自己的环境下,根据操作静下心来一步步看。阅读源码本身是一个比较费神的操作,建议大家一定要多看 看明白后自己在把大体思路捋一下。 因为springboot用的也是spirng 所以下面介绍主要是spirng 而不是springboot 特此说明。

2 通过BeanPostProcessor 进行Bean 初始化回调前后进行自定义操作

我们知道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 

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第1张图片

为什么实现 BeanPostProcessor就可以进行bean初始化后的操作呢?想知道其中的原理我们就要去看看spring的源码了。

第一步在MyBeanPostProcessor postProcessAfterInitialization方法中打一个段断点 然后启动spirngboot项目玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第2张图片

当断点走到 postProcessAfterInitialization 方法上事 如下图它的调用链就出来了,是不是很清晰。

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第3张图片

根据上图调用链我们继续查看 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) () -> { 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; }

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 调用时序图如下:中间很多流程做了简化 画的是核心的逻辑。

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第4张图片

还有一个问题就是我们的 BeanPostProcessor 集合是在什么时添加的?关闭到我们的springboot服务

还是下图的断点 在次一debug方式启动

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第5张图片

通过调用的链路往下找 知道找到 AbstractApplicationContext 中的refresh() 方法中的 registerBeanPostProcessors(beanFactory) 

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第6张图片

通过PostProcessorRegistrationDelegate.registerBeanPostProcessors 将 放入到beanFactory 中

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第7张图片

 registerBeanPostProcessors 方法中获取到所有的BeanPostProcessor 然后放入集合中

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第8张图片

 然后再将BeanPostProcessor集合 放入到 beanFactory 中

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第9张图片

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第10张图片

 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 方法流程。

 

玩转SpringBoot 2.x 解析BeanPostProcessor原理篇_第11张图片

大致流程如下: 

在 Spring 初始化完成后会回调 GenericApplicationContext 中的 refresh 方法,然后再通过AbstractApplicationContext  抽象类中的 refresh 来实现。

在refresh 方法中registerBeanPostProcessors 调用了 PostProcessorRegistrationDelegate,将 BeanFactory 作为参数传入,在registerBeanPostProcessors中获取所有的BeanPostProcessor获取完所有实现类后,根据实现类上的顺序进行排序,然后将排序好的集合对象调用BeanFactory.addBeanPostProcessor 注册到 BeanFactory 中。

这样在 AbstractAutowireCapableBeanFactory 中就可以从它的父类 AbstractBeanFactory 中直接获取到 BeanPostProcessor 集合对象了,也就是上面调用的 getBeanPostProcessors() 方法。

 

你可能感兴趣的:(【SpringBoot】,springboot,springboot原理)