AbstractAutoProxyCreator
是Spring AOP
提供的一个SmartInstantiationAwareBeanPostProcessor
,它的作用是将符合条件的bean
包装成代理对象,包装成代理对象的过程会在bean
实例外面包裹相应的AOP
拦截器。调用者对该bean
的方法调用,其实首先发生在相应的代理上,经过层层包裹的AOP
拦截器之后,才真正执行目标bean
的方法。
AbstractAutoProxyCreator
将AOP
拦截器分为两类 :
bean
的拦截器AbstractAutoProxyCreator
会在SmartInstantiationAwareBeanPostProcessor
接口定义的合适的bean
生命周期回调方法中对bean
进行相应的代理对象创建,主要是如下三个方法 :
Object postProcessBeforeInstantiation(Class> beanClass, String beanName)
由接口
InstantiationAwareBeanPostProcessor
定义
Object postProcessAfterInitialization(@Nullable Object bean, String beanName)
由接口
BeanPostProcessor
定义
Object getEarlyBeanReference(Object bean, String beanName)
由接口
SmartInstantiationAwareBeanPostProcessor
定义
AbstractAutoProxyCreator
存在的主要意义在于简化bean
定义。想象一下,你有很多bean
需要定义,这些bean
需要类似的代理行为,比如都需要被同样的一些拦截器包裹,如果没有AbstractAutoProxyCreator
,你需要一个个重复这些bean
定义的工作。而有了AbstractAutoProxyCreator
,它就能自动替你完成这些工作。
另外,AbstractAutoProxyCreator
是一个抽象基类,它的如下抽象方法必须由实现子类提供:
// 找到某个 bean 专有的拦截器对象
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
@Nullable TargetSource customTargetSource) throws BeansException;
源代码版本 : spring-aop-5.1.5.RELEASE
package org.springframework.aop.framework.autoproxy;
// 省略 import 行
@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
/**
* Convenience constant for subclasses: Return value for "do not proxy".
* @see #getAdvicesAndAdvisorsForBean
*/
@Nullable
protected static final Object[] DO_NOT_PROXY = null;
/**
* Convenience constant for subclasses: Return value for
* "proxy without additional interceptors, just the common ones".
* @see #getAdvicesAndAdvisorsForBean
*/
protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];
/** Logger available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
/** Default is global AdvisorAdapterRegistry. */
// 用于将各种类型的拦截器适配成 Spring Advisor 的工具,缺省值是一个 DefaultAdvisorAdapterRegistry 对象,
// 当前 BeanPostProcessor 使用者可以从外部设定一个不同值
// 1. 来源类型可能是 Spring Advisor, 或者 AOP 标准 MethodInterceptor,
// 2. 目标类型统一包装变成 Spring Advisor : org.springframework.aop.Advisor
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
/**
* Indicates whether or not the proxy should be frozen. Overridden from super
* to prevent the configuration from becoming frozen too early.
*/
private boolean freezeProxy = false;
/** Default is no common interceptors. */
// 通用拦截器bean的名称,需要当前 BeanPostProcessor 使用者从外部设置,缺省为空
// 该信息会被用于从容器获得相应的拦截器 bean 实例
private String[] interceptorNames = new String[0];
// 创建某个bean的代理对象时,先应用通用拦截器还是先应用专用拦截器,
// true 表示先应用通用拦截器
private boolean applyCommonInterceptorsFirst = true;
@Nullable
private TargetSourceCreator[] customTargetSourceCreators;
@Nullable
private BeanFactory beanFactory;
// cache : 记录 targetSource 不为 null 的 bean 的名称
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// cache : key 通过方法 #getCacheKey 计算
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
// cache : key 通过方法 #getCacheKey 计算
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
// cache : key 通过方法 #getCacheKey 计算
// 某一个 entry 的值为 true 表示该 bean 已经创建代理对象,
// 为 false 表示经过检测已经判断出该 bean 不需要创建代理对象
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
/**
* Set whether or not the proxy should be frozen, preventing advice
* from being added to it once it is created.
* Overridden from the super class to prevent the proxy configuration
* from being frozen before the proxy is created.
*/
@Override
public void setFrozen(boolean frozen) {
this.freezeProxy = frozen;
}
@Override
public boolean isFrozen() {
return this.freezeProxy;
}
/**
* Specify the AdvisorAdapterRegistry to use.
* Default is the global AdvisorAdapterRegistry.
* @see org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry
*/
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}
/**
* Set custom TargetSourceCreators to be applied in this order.
* If the list is empty, or they all return null, a SingletonTargetSource
* will be created for each bean.
* Note that TargetSourceCreators will kick in even for target beans
* where no advices or advisors have been found. If a TargetSourceCreator
* returns a TargetSource for a specific bean, that bean will be proxied
* in any case.
* TargetSourceCreators can only be invoked if this post processor is used
* in a BeanFactory and its BeanFactoryAware callback is triggered.
* @param targetSourceCreators the list of TargetSourceCreators.
* Ordering is significant: The TargetSource returned from the first matching
* TargetSourceCreator (that is, the first that returns non-null) will be used.
*/
public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
this.customTargetSourceCreators = targetSourceCreators;
}
/**
* Set the common interceptors. These must be bean names in the current factory.
* They can be of any advice or advisor type Spring supports.
* If this property isn't set, there will be zero common interceptors.
* This is perfectly valid, if "specific" interceptors such as matching
* Advisors are all we want.
*/
public void setInterceptorNames(String... interceptorNames) {
this.interceptorNames = interceptorNames;
}
/**
* Set whether the common interceptors should be applied before bean-specific ones.
* Default is "true"; else, bean-specific interceptors will get applied first.
*/
public void setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst) {
this.applyCommonInterceptorsFirst = applyCommonInterceptorsFirst;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
/**
* Return the owning BeanFactory.
* May be null, as this post-processor doesn't need to belong to a bean factory.
*/
@Nullable
protected BeanFactory getBeanFactory() {
return this.beanFactory;
}
@Override
@Nullable
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
if (this.proxyTypes.isEmpty()) {
return null;
}
Object cacheKey = getCacheKey(beanClass, beanName);
return this.proxyTypes.get(cacheKey);
}
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
// 尝试使用自定义的 TargetSourceCreator[] this.customTargetSourceCreators 创建目标bean
// 的 TargetSource
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
// 如果使用自定义的 TargetSourceCreator[] this.customTargetSourceCreators 能够创建出目标bean
// 的 TargetSource , 则在该生命周期回调方法中创建该 bean 的代理对象
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 获取针对该bean的所有专用拦截器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 创建该bean的代理对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回所创建的代理对象
return proxy;
}
// 返回 null 表示当前方法没有做任何处理,接下来的生命周期方法继续进行
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
/**
* Build a cache key for the given bean class and bean name.
* Note: As of 4.2.3, this implementation does not return a concatenated
* class/name String anymore but rather the most efficient cache key possible:
* a plain bean name, prepended with BeanFactory#FACTORY_BEAN_PREFIX
* in case of a FactoryBean; or if no bean name specified, then the
* given bean Class as-is.
* @param beanClass the bean class
* @param beanName the bean name
* @return the cache key for the given class and name
*/
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
if (StringUtils.hasLength(beanName)) {
return (FactoryBean.class.isAssignableFrom(beanClass) ?
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
}
else {
return beanClass;
}
}
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
// 这种情况说明 bean 已经被方法 #postProcessBeforeInstantiation 处理过,这里不再处理
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
// 之前的逻辑已经检测到该bean不需要代理,相应的信息记录在缓存 this.advisedBeans 中
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 如果这是一个基础设施bean 或者 需要被跳过的 bean, 则也不需要对其进行代理包装
// 同时将该信息记录到缓存 this.advisedBeans
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 获取针对该bean的所有专用拦截器对象,对返回值数组需要分三种情况考虑 :
// 1. 返回数组有值 : 需要做代理,使用专用拦截器和通用拦截器
// 2. 返回数组无值,为空 : 需要做代理,仅使用通用拦截器
// 3. 返回为null : 不要给当前 bean 做代理
// 当前类 getAdvicesAndAdvisorsForBean 方法其实是一个抽象方法,具体实现由实现子类提供
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 缓存当前bean代理对象已创建
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 缓存代理对象类型
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理对象
return proxy;
}
// 缓存当前bean不要创建代理对象
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
/**
* Return whether the given bean class represents an infrastructure class
* that should never be proxied.
* The default implementation considers Advices, Advisors and
* AopInfrastructureBeans as infrastructure classes.
* @param beanClass the class of the bean
* @return whether the bean represents an infrastructure class
* @see org.aopalliance.aop.Advice
* @see org.springframework.aop.Advisor
* @see org.springframework.aop.framework.AopInfrastructureBean
* @see #shouldSkip
*/
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
/**
* Subclasses should override this method to return true if the
* given bean should not be considered for auto-proxying by this post-processor.
* Sometimes we need to be able to avoid this happening, e.g. if it will lead to
* a circular reference or if the existing target instance needs to be preserved.
* This implementation returns false unless the bean name indicates an
* "original instance" according to AutowireCapableBeanFactory conventions.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @return whether to skip the given bean
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX
*/
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
/**
* Create a target source for bean instances. Uses any TargetSourceCreators if set.
* Returns null if no custom TargetSource should be used.
* This implementation uses the "customTargetSourceCreators" property.
* Subclasses can override this method to use a different mechanism.
* @param beanClass the class of the bean to create a TargetSource for
* @param beanName the name of the bean
* @return a TargetSource for this bean
* @see #setCustomTargetSourceCreators
*/
@Nullable
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
// We can't create fancy target sources for directly registered singletons.
if (this.customTargetSourceCreators != null &&
this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
TargetSource ts = tsc.getTargetSource(beanClass, beanName);
if (ts != null) {
// Found a matching TargetSource.
if (logger.isTraceEnabled()) {
logger.trace("TargetSourceCreator [" + tsc +
"] found custom TargetSource for bean with name '" + beanName + "'");
}
return ts;
}
}
}
// No custom TargetSource found.
return null;
}
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass(
(ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 将针对当前 bean 的所有的专用拦截器和容器中的通用拦截器一并包装成 Spring Advisor 对象
// 用于创建最终的代理对象
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
// 定制化 proxyFactory, 方法#customizeProxyFactory在本类是一个空方法,
// 这里主要是留给实现子类一个定制 proxyFactory 的机会
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// proxyFactory 已经拥有了足够多的创建代理对象的信息,现在使用它创建
// 当前 bean 的代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
/**
* Determine whether the given bean should be proxied with its target class rather than its interfaces.
* Checks the AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute
* of the corresponding bean definition.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @return whether the given bean should be proxied with its target class
* @see AutoProxyUtils#shouldProxyTargetClass
*/
protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
AutoProxyUtils.shouldProxyTargetClass(
(ConfigurableListableBeanFactory) this.beanFactory, beanName));
}
/**
* Return whether the Advisors returned by the subclass are pre-filtered
* to match the bean's target class already, allowing the ClassFilter check
* to be skipped when building advisors chains for AOP invocations.
* Default is false. Subclasses may override this if they
* will always return pre-filtered Advisors.
* @return whether the Advisors are pre-filtered
* @see #getAdvicesAndAdvisorsForBean
* @see org.springframework.aop.framework.Advised#setPreFiltered
*/
protected boolean advisorsPreFiltered() {
return false;
}
/**
* Determine the advisors for the given bean, including the specific interceptors
* as well as the common interceptor, all adapted to the Advisor interface.
* 1. 根据 this.interceprotNames 找到所有通用拦截器 bean
* 2. 根据 this.applyCommonInterceptorsFirst 设置将通用拦截器和专用拦截器放到同一个列表中
* 3. 将拦截器列表中的每个拦截器都包装成Spring Advisor 然后返回该 Spring Advisor 数组
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @return the list of Advisors for the given bean
*/
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
// 根据所设置的通用拦截器bean的名称(this.interceprotNames)获取相应的bean实例,并将其均包装成 Spring Advisor
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
// 参数 specificInterceptors 表示的是针对当前操作的 bean 的专用拦截器对象
if (specificInterceptors != null) {
// 如果指定了专用拦截器,则应用它们
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
// 根据属性 this.applyCommonInterceptorsFirst 决定通用拦截器/专用拦截器的应用顺序
if (this.applyCommonInterceptorsFirst) {
// 将通用拦截器放到专用拦截器前面
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
// 将专用拦截器放到通用拦截器前面
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 将上面获取的所有拦截器统一包装成 Spring Advisor
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
/**
* Resolves the specified interceptor names to Advisor objects.
* this.interceptorNames 记录的是拦截器bean的名字,该方法根据这些bean的名字找到相应的拦截器对象,
* 相应的拦截器bean可能是 Spring Advisor 或者 AOP MethodInterceptor, 该方法使用工具
* this.advisorAdapterRegistry 将它们统一包装成 Spring Advisor 并返回
* @see #setInterceptorNames
*/
private Advisor[] resolveInterceptorNames() {
BeanFactory bf = this.beanFactory;
ConfigurableBeanFactory cbf =
(bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
List<Advisor> advisors = new ArrayList<>();
for (String beanName : this.interceptorNames) {
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
Object next = bf.getBean(beanName);
advisors.add(this.advisorAdapterRegistry.wrap(next));
}
}
return advisors.toArray(new Advisor[0]);
}
/**
* Subclasses may choose to implement this: for example,
* to change the interfaces exposed.
* The default implementation is empty.
* @param proxyFactory a ProxyFactory that is already configured with
* TargetSource and interfaces and will be used to create the proxy
* immediately after this method returns
*/
protected void customizeProxyFactory(ProxyFactory proxyFactory) {
}
/**
* Return whether the given bean is to be proxied, what additional
* advices (e.g. AOP Alliance interceptors) and advisors to apply.
* 返回针对指定bean的专用拦截器对象(AOP Interceptor 或者 Spring Advisor)列表,
* 如果返回空数组则表明参数bean没有相应的专用拦截器,
* 如果返回null表示参数bean不需要创建代理对象
* 抽象方法,具体实现子类要负责提供实现
* @param beanClass the class of the bean to advise
* @param beanName the name of the bean
* @param customTargetSource the TargetSource returned by the
* #getCustomTargetSource method: may be ignored.
* Will be null if no custom target source is in use.
* @return an array of additional interceptors for the particular bean;
* or an empty array if no additional interceptors but just the common ones;
* or null if no proxy at all, not even with the common interceptors.
* See constants DO_NOT_PROXY and PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS.
* @throws BeansException in case of errors
* @see #DO_NOT_PROXY
* @see #PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
*/
@Nullable
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
@Nullable TargetSource customTargetSource) throws BeansException;
}