BeanPostProcessor机制
Posted 恒奇恒毅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BeanPostProcessor机制相关的知识,希望对你有一定的参考价值。
BeanPostProcessor
及子类介绍
/**
* Factory hook that allows for custom modification of new bean instances,
* e.g. checking for marker interfaces or wrapping them with proxies.
*
* <p>ApplicationContexts can autodetect BeanPostProcessor beans in their
* bean definitions and apply them to any beans subsequently created.
* Plain bean factories allow for programmatic registration of post-processors,
* applying to all beans created through this factory.
*
* <p>Typically, post-processors that populate beans via marker interfaces
* or the like will implement @link #postProcessBeforeInitialization,
* while post-processors that wrap beans with proxies will normally
* implement @link #postProcessAfterInitialization.
*
* @author Juergen Hoeller
* @since 10.10.2003
* @see InstantiationAwareBeanPostProcessor
* @see DestructionAwareBeanPostProcessor
* @see ConfigurableBeanFactory#addBeanPostProcessor
* @see BeanFactoryPostProcessor
*/
public interface BeanPostProcessor
/**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's @code afterPropertiesSet
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if @code null, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's @code afterPropertiesSet
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding @code bean instanceof FactoryBean checks.
* <p>This callback will also be invoked after a short-circuiting triggered by a
* @link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation method,
* in contrast to all other BeanPostProcessor callbacks.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if @code null, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
BeanPostProcssor
是Spring提供的工厂钩子方法,用于拦截每一个Bean对象的创建过程,接口有两个方法,Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
和Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
,分别在Bean对象创建后初始化方法(比如init-method、InitializingBean#afterPropertiesSet)调用前后进行调用,此时Bean的属性值已经被设置好了。容器可以自动发现BeanPostProcessor
,我们只需要将其放入容器即可。他有一些提供更强功能的子类接口:
InstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor
MergedBeanDefinitionPostProcessor
DestructionAwareBeanPostProcessor
/**
* Subinterface of @link BeanPostProcessor that adds a before-instantiation callback,
* and a callback after instantiation but before explicit properties are set or
* autowiring occurs.
*
* <p>Typically used to suppress default instantiation for specific target beans,
* for example to create proxies with special TargetSources (pooling targets,
* lazily initializing targets, etc), or to implement additional injection strategies
* such as field injection.
*
* <p><b>NOTE:</b> This interface is a special purpose interface, mainly for
* internal use within the framework. It is recommended to implement the plain
* @link BeanPostProcessor interface as far as possible, or to derive from
* @link InstantiationAwareBeanPostProcessorAdapter in order to be shielded
* from extensions to this interface.
*
* @author Juergen Hoeller
* @author Rod Johnson
* @since 1.2
* @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#setCustomTargetSourceCreators
* @see org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator
*/
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor
/**
* Apply this BeanPostProcessor <i>before the target bean gets instantiated</i>.
* The returned bean object may be a proxy to use instead of the target bean,
* effectively suppressing default instantiation of the target bean.
* <p>If a non-null object is returned by this method, the bean creation process
* will be short-circuited. The only further processing applied is the
* @link #postProcessAfterInitialization callback from the configured
* @link BeanPostProcessor BeanPostProcessors.
* <p>This callback will only be applied to bean definitions with a bean class.
* In particular, it will not be applied to beans with a "factory-method".
* <p>Post-processors may implement the extended
* @link SmartInstantiationAwareBeanPostProcessor interface in order
* to predict the type of the bean object that they are going to return here.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to expose instead of a default instance of the target bean,
* or @code null to proceed with default instantiation
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#hasBeanClass
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getFactoryMethodName
*/
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
/**
* Perform operations after the bean has been instantiated, via a constructor or factory method,
* but before Spring property population (from explicit properties or autowiring) occurs.
* <p>This is the ideal callback for performing custom field injection on the given bean
* instance, right before Spring's autowiring kicks in.
* @param bean the bean instance created, with properties not having been set yet
* @param beanName the name of the bean
* @return @code true if properties should be set on the bean; @code false
* if property population should be skipped. Normal implementations should return @code true.
* Returning @code false will also prevent any subsequent InstantiationAwareBeanPostProcessor
* instances being invoked on this bean instance.
* @throws org.springframework.beans.BeansException in case of errors
*/
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
/**
* Post-process the given property values before the factory applies them
* to the given bean. Allows for checking whether all dependencies have been
* satisfied, for example based on a "Required" annotation on bean property setters.
* <p>Also allows for replacing the property values to apply, typically through
* creating a new MutablePropertyValues instance based on the original PropertyValues,
* adding or removing specific values.
* @param pvs the property values that the factory is about to apply (never @code null)
* @param pds the relevant property descriptors for the target bean (with ignored
* dependency types - which the factory handles specifically - already filtered out)
* @param bean the bean instance created, but whose properties have not yet been set
* @param beanName the name of the bean
* @return the actual property values to apply to the given bean
* (can be the passed-in PropertyValues instance), or @code null
* to skip property population
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.MutablePropertyValues
*/
PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
InstantiationAwareBeanPostProcessor
接口增加了Bean实例化之前的回调方法Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
和实例化之后但是属性值或者自动装配之前的回调方法boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
,以及PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
。
此类最典型的应用通常用于拦截特定目标bean的默认实例化,例如,创建特定TargetSources(pooling targets, lazily initializing targets, etc)的代理,或实施额外的注入策略比如按照Field注入。此接口主要用于框架自己,不建议程序猿使用。类似的其子类SmartInstantiationAwareBeanPostProcessor
提供了以下三个方法供框架使用。
/**
* Extension of the @link InstantiationAwareBeanPostProcessor interface,
* adding a callback for predicting the eventual type of a processed bean.
*
* <p><b>NOTE:</b> This interface is a special purpose interface, mainly for
* internal use within the framework. In general, application-provided
* post-processors should simply implement the plain @link BeanPostProcessor
* interface or derive from the @link InstantiationAwareBeanPostProcessorAdapter
* class. New methods might be added to this interface even in point releases.
*
* @author Juergen Hoeller
* @since 2.0.3
* @see InstantiationAwareBeanPostProcessorAdapter
*/
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
/**
* Predict the type of the bean to be eventually returned from this
* processor's @link #postProcessBeforeInstantiation callback.
* @param beanClass the raw class of the bean
* @param beanName the name of the bean
* @return the type of the bean, or @code null if not predictable
* @throws org.springframework.beans.BeansException in case of errors
*/
Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;
/**
* Determine the candidate constructors to use for the given bean.
* @param beanClass the raw class of the bean (never @code null)
* @param beanName the name of the bean
* @return the candidate constructors, or @code null if none specified
* @throws org.springframework.beans.BeansException in case of errors
*/
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;
/**
* Obtain a reference for early access to the specified bean,
* typically for the purpose of resolving a circular reference.
* <p>This callback gives post-processors a chance to expose a wrapper
* early - that is, before the target bean instance is fully initialized.
* The exposed object should be equivalent to the what
* @link #postProcessBeforeInitialization / @link #postProcessAfterInitialization
* would expose otherwise. Note that the object returned by this method will
* be used as bean reference unless the post-processor returns a different
* wrapper from said post-process callbacks. In other words: Those post-process
* callbacks may either eventually expose the same reference or alternatively
* return the raw bean instance from those subsequent callbacks (if the wrapper
* for the affected bean has been built for a call to this method already,
* it will be exposes as final bean reference by default).
* @param bean the raw bean instance
* @param beanName the name of the bean
* @return the object to expose as bean reference
* (typically with the passed-in bean instance as default)
* @throws org.springframework.beans.BeansException in case of errors
*/
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
/**
* Post-processor callback interface for <i>merged</i> bean definitions at runtime.
* @link BeanPostProcessor implementations may implement this sub-interface in order
* to post-process the merged bean definition (a processed copy of the original bean
* definition) that the Spring @code BeanFactory uses to create a bean instance.
*
* <p>The @link #postProcessMergedBeanDefinition method may for example introspect
* the bean definition in order to prepare some cached metadata before post-processing
* actual instances of a bean. It is also allowed to modify the bean definition but
* <i>only</i> for definition properties which are actually intended for concurrent
* modification. Essentially, this only applies to operations defined on the
* @link RootBeanDefinition itself but not to the properties of its base classes.
*
* @author Juergen Hoeller
* @since 2.5
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getMergedBeanDefinition
*/
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor
/**
* Post-process the given merged bean definition for the specified bean.
* @param beanDefinition the merged bean definition for the bean
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
MergedBeanDefinitionPostProcessor
提供了运行时处理merged bean definitions的能力。这三个类的典型实现是RequiredAnnotationBeanPostProcessor
和AutowiredAnnotationBeanPostProcessor
,用于处理@Requied
和@Autowired
、@Value
注解。
/**
* Subinterface of @link BeanPostProcessor that adds a before-destruction callback.
*
* <p>The typical usage will be to invoke custom destruction callbacks on
* specific bean types, matching corresponding initialization callbacks.
*
* @author Juergen Hoeller
* @since 1.0.1
*/
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor
/**
* Apply this BeanPostProcessor to the given bean instance before
* its destruction. Can invoke custom destruction callbacks.
* <p>Like DisposableBean's @code destroy and a custom destroy method,
* this callback just applies to singleton beans in the factory (including
* inner beans).
* @param bean the bean instance to be destroyed
* @param beanName the name of the bean
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#setDestroyMethodName
*/
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
/**
* Determine whether the given bean instance requires destruction by this
* post-processor.
* <p><b>NOTE:</b> Even as a late addition, this method has been introduced on
* @code DestructionAwareBeanPostProcessor itself instead of on a SmartDABPP
* subinterface. This allows existing @code DestructionAwareBeanPostProcessor
* implementations to easily provide @code requiresDestruction logic while
* retaining compatibility with Spring <4.3, and it is also an easier onramp to
* declaring @code requiresDestruction as a Java 8 default method in Spring 5.
* <p>If an implementation of @code DestructionAwareBeanPostProcessor does
* not provide a concrete implementation of this method, Spring's invocation
* mechanism silently assumes a method returning @code true (the effective
* default before 4.3, and the to-be-default in the Java 8 method in Spring 5).
* @param bean the bean instance to check
* @return @code true if @link #postProcessBeforeDestruction is supposed to
* be called for this bean instance eventually, or @code false if not needed
* @since 4.3
*/
boolean requiresDestruction(Object bean);
DestructionAwareBeanPostProcessor
提供了Bean销毁之前的回调方法void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
其典型实现有ApplicationListenerDetector
用于处理ApplicationListener的添加和销毁、InitDestroyAnnotationBeanPostProcessor
用于处理@PostConstruct
和@PreDestroy
、ScheduledAnnotationBeanPostProcessor
用于处理@Scheduled
注解。
注册时机
BeanPostProcessor
的运行机制是先注册,后使用。注册是在AbstractApplicationContext#refresh
方法中。使用就是在Bean对象的初始化前后进行使用。
registerBeanPostProcessors方法委托给PostProcessorRegistrationDelegate#registerBeanPostProcessors(ConfigurableListableBeanFactory,AbstractApplicationContext)
。
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<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
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(beanFactory, priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames)
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor)
internalPostProcessors.add(pp);
sortPostProcessors(beanFactory, orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
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(beanFactory, internalPostProcessors);
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));
按照实现了以下接口PriorityOrdered、Ordered和无顺序接口分别进行注册,其中实现了MergedBeanDefinitionPostProcessor
接口的还额外添加了一次。最后添加了一个ApplicationListenerDetector
,用于获取容器中的ApplicationListener进行注册。添加方法使用BeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
。此时容器中已经保存的是BeanPostProcessor
的实例,因为已经调用BeanFactory#getBean
方法。关于MergedBeanDefinitionPostProcessor
接口,虽然通过internalPostProcessors重新添加了一次,但是并不会重复添加,因为addBeanPostProcessor方法是先remove,再add,这些BeanPostProcessor
就会添加到最后。
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor)
this.hasInstantiationAwareBeanPostProcessors = true;
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor)
this.hasDestructionAwareBeanPostProcessors = true;
介入时机
经过以上的步骤,此时容器中已经包含了所有的BeanPostProcessor
,在其他Bean创建的时候,这些BeanPostProcessor
就会介入工作。
在AbstractAutowireCapableBeanFactory#createBean
方法中,首先给InstantiationAwareBeanPostProcessor一个机会创建对象的代理。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved))
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors())
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null)
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null)
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
mbd.beforeInstantiationResolved = (bean != null);
return bean;
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
for (BeanPostProcessor bp : getBeanPostProcessors())
if (bp instanceof InstantiationAwareBeanPostProcessor)
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null)
return result;
return null;
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors())
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null)
return result;
return result;
首先调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation创建对象,不为空则直接返回,所以,最多只有一个InstantiationAwareBeanPostProcessor会起作用。然后调用所有的BeanPostProcessor
的postProcessAfterInitialization方法。
如果以上方法返回null,则说明需要走Bean创建流程,就调用AbstractAutowireCapableBeanFactory#doCreateBean
方法。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final 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 != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
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.isDebugEnabled())
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
addSingletonFactory(beanName, new ObjectFactory<Object>()
@Override
public Object getObject() throws BeansException 以上是关于BeanPostProcessor机制的主要内容,如果未能解决你的问题,请参考以下文章
BeanPostProcessor —— 连接Spring IOC和AOP的桥梁
死磕 Spring----- IOC 之 深入分析 BeanFactoryPostProcessor