BeanPostProcess简介
在Spring中 BeanPostProcessor 是一个非常重要的接口,它用于在每个bean对象初始化前后修改Bean的属性信息,比如我们最常用的@Autowired注解,在内部处理的时候,是通过一个AutowiredAnnotationBeanPostProcessor类来对bean的属性进行自动注入的,而AutowiredAnnotationBeanPostProcessor也是 BeanPostProcessor的一个实现类。它在createBean的时候会被调用。
1. Spring createBean基本流程图
在Spring中创建Bean对象,我们可以把它看作是两个过程
- 实例化(Spring中通过反射工具进行实例化对象,并将属性设为默认值)
-
初始化(Spring中在初始化前化给属性进行注入操作)
Bean初始化过程
2. BeanPostProcess接口定义
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;
}
}
它提供了两个方法,一个前置和后置的处理方法,在bean对象实例化前后分别被调用,并会传入一个将要被处理的bean对象,从上面图中我们可以看出,BeanPostProcessor的before 和 after是在init-method前后调用的,我们一起来看一下,createBean的时候这一部分的源码,在createBean的时候,会调用 doCreateBean,所以真正核心的创建流程在doCreateBean方法中
3. doCreateBean (singleton bean)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
在以上创建过程中,我们可以看到几个重要的方法
1. createBeanInstance 实例化Bean对象
2. populateBean 为Bean对象填充属性
3. initializeBean 初始化bean对象
4. 初始化Bean对象
在initializeBean 方法中
protected Object initializeBean(final String beanName, final 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;
}
首先会调用invokeAwareMethods方法,处理几个特殊的aware接口(BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
),以便在后面的处理过程中可能会使用到,所以提前处理
其它的Aware接口会通过BeanPostProcessor去处理。
重点来了
applyBeanPostProcessorsBeforeInitialization 通过调用此方法去遍历Spring容器中的 BeanPostProcessor
,并执行其 postProcessBeforeInitialization
方法
invokeInitMethods 通过调用此方法完成以下的一些操作
- afterPropertiesSet方法的调用
- 调用自定义的init-method方法
applyBeanPostProcessorsAfterInitialization 通过调用此方法去遍历Spring容器中的 BeanPostProcessor
,并执行其 postProcessAfterInitialization
方法
在applyBeanPostProcessorsBeforeInitialization中我可以看到我们常用的一些BeanPostProcessor调用
- ApplicationContextAwarePostProcessor 处理我们的几个Spring中提供的Aware接口
EnvironmentAware
、EmbeddedValueResolverAware
、ResourceLoaderAware
、ApplicationEventPublisherAware
、MessageSourceAware
、ApplicationContextAware
- ImportAwareBeanPostProcessor 处理被import注解了的bean对象,并进行递归import bean对象
详细的流程图如下
自定义BeanPostProcessor
需要:自定义一个BeanPostProcessor用于打印输出 每个bean 初始化成功的消息
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
/**
* BeanPostProcessor 接口里有默认方法,默认直接将bean返回
*
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* 在后置处理器中,可以对bean对象进行修改操作
* 1. 可以返回其代理对象
* <p>
* 我们这里只输出一下bean创建成功的消息
*
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + " init successful");
return bean;
}
另外一篇里面也有关于BeanPostProcessor的扩展——https://www.cnblogs.com/yanchuanbin/p/14582813.html