Spring - SmartInstantiationAwareBeanPostProcessor扩展接口
Posted 小小工匠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring - SmartInstantiationAwareBeanPostProcessor扩展接口相关的知识,希望对你有一定的参考价值。
文章目录
- Pre
- org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
- 类关系
- SmartInstantiationAwareBeanPostProcessor接口方法
- 扩展示例
Pre
org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
import java.lang.reflect.Constructor;
import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;
/**
* 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.
* <p>The default implementation returns @code null.
* @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
*/
@Nullable
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException
return null;
/**
* Determine the candidate constructors to use for the given bean.
* <p>The default implementation returns @code null.
* @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
*/
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
throws BeansException
return null;
/**
* 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).
* <p>The default implementation returns the given @code bean as-is.
* @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
*/
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException
return bean;
类关系
SmartInstantiationAwareBeanPostProcessor接口方法
该扩展接口有3个触发点方法
predictBeanType(Class<?> beanClass, String beanName)
在
postProcessBeforeInstantiation
之前(一般不太需要扩展这个点),这个方法用于预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null;当调用BeanFactory.getType(name)
时当通过bean的名字无法得到bean类型信息时就调用该回调方法来决定类型信息。
-
determineCandidateConstructors(Class<?> beanClass, String beanName)
发生在
postProcessBeforeInstantiation
之后,用于确定该bean的构造函数之用,返回的是该bean的所有构造函数列表。可以扩展这个点,来自定义选择相应的构造器来实例化这个bean。 -
getEarlyBeanReference(Object bean, String beanName)
发生在
postProcessAfterInstantiation
之后,当有循环依赖的场景,当bean实例化好之后,为了防止有循环依赖,会提前暴露回调方法,用于bean实例化的后置处理。这个方法就是在提前暴露的回调方法中触发。举个例子
<bean id="aa" class="com.artisan.A">
<property name="b" ref="bb"/>
</bean>
<bean id="bb" class="com.artisan.B" >
<property name="a" ref="aa"/>
</bean>
加载aa,提前将singleton露出去,这个时候只getEarlyBeanReferencei
没有被调用; 因为没有出现循环引用的情况,现在放入缓存是为了预防有循环引用的情况可以通过这个getEarlyBeanReference
取对象;
源码调用的地方如下
// 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));
继续看 getEarlyBeanReference(beanName, mbd, bean)
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
org.springframework.beans.factory.support.AbstractBeanFactory#getBean
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference
/**
* Obtain a reference for early access to the specified bean,
* typically for the purpose of resolving a circular reference.
* @param beanName the name of the bean (for error handling purposes)
* @param mbd the merged bean definition for the bean
* @param bean the raw bean instance
* @return the object to expose as bean reference
*/
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean)
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors())
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware)
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
return exposedObject;
紧接着 属性填充
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
在填充属性的时候发现引用了b;然后就去获取bb来填充 , 重复刚才的动作,然后直接调用getSingleton获取
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or @code null if none found
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference)
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference)
synchronized (this.singletonObjects)
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null)
// 调用getEarlyBeanReference的地方了;
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
return singletonObject;
扩展示例
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
import java.lang.reflect.Constructor;
/**
* @author 小工匠
* @version 1.0
* @description: TODO
* @date 2022/12/3 23:49
* @mark: show me the code , change the world
*/
@Slf4j
@Component
public class ExtendSmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor
@Override
public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException
log.info("[ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType " ,beanName);
return beanClass;
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException
log.info("[ExtendSmartInstantiationAwareBeanPostProcessor] determineCandidateConstructors " ,beanName);
return null;
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException
log.info("[ExtendSmartInstantiationAwareBeanPostProcessor] getEarlyBeanReference " ,beanName);
return bean;
输出
. ____ _ __ _ _
/\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\
( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\
\\\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.2)
2022-12-04 08:36:13.363 INFO 20848 --- [ main] .b.t.ExtendApplicationContextInitializer : ExtendApplicationContextInitializer # initialize Called
2022-12-04 08:36:13.373 INFO 20848 --- [ main] c.a.b.BootSpringExtendApplication : Starting BootSpringExtendApplication using Java 1.8.0_261 on LAPTOP-JF3RBRRJ with PID 20848 (D:\\IdeaProjects\\boot2\\boot-spring-extend\\target\\classes started by artisan in D:\\IdeaProjects\\boot2)
2022-12-04 08:36:13.374 INFO 20848 --- [ main] c.a.b.BootSpringExtendApplication : No active profile set, falling back to default profiles: default
2022-12-04 08:36:13.657 INFO 20848 --- [ main] xtendBeanDefinitionRegistryPostProcessor : ---->postProcessBeanDefinitionRegistry
2022-12-04 08:36:13.658 INFO 20848 --- [ main] o.s.c.a.ConfigurationClassPostProcessor : Cannot enhance @Configuration bean definition 'extendBeanDefinitionRegistryPostProcessor' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
2022-12-04 08:36:13.710 INFO 20848 --- [ main] xtendBeanDefinitionRegistryPostProcessor : ---->postProcessBeanFactory
2022-12-04 08:36:13.710 INFO 20848 --- [ main] xtendBeanDefinitionRegistryPostProcessor : com.artisan.bootspringextend.service.ArtisanServiceImpl
2022-12-04 08:36:13.711 INFO 20848 --- [ main] c.a.b.service.ArtisanServiceImpl : -------> ArtisanServiceImpl#doSomething called
2022-12-04 08:36:13.717 INFO 20848 --- [ main] c.a.b.t.ExtendBeanFactoryPostProcessor : ----->postProcessBeanFactory called
2022-12-04 08:36:13.729 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType bootSpringExtendApplication
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType classA
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType org.springframework.boot.autoconfigure.AutoConfigurationPackages
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType mbeanExporter
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType objectNamingStrategy
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType mbeanServer
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType springApplicationAdminRegistrar
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration
2022-12-04 08:36:13.730 INFO 20848 --- [ main] SmartInstantiationAwareBeanPostProcessor : [ExtendSmartInstantiationAwareBeanPostProcessor] predictBeanType applicationAvailability
2022-12-04 Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC
学习笔记——Spring简介;Spring搭建步骤;Spring的特性;Spring中getBean三种方式;Spring中的标签
Spring框架--Spring事务管理和Spring事务传播行为