概述
BeanNameAutoProxyCreator
是Spring AOP
内置的一个APC
,它根据bean
名称匹配需要创建代理对象的bean
。
使用者需要为BeanNameAutoProxyCreator
指定需要被代理的bean
的名称通配符,比如myBean
,tx*
这样的字符串,然后BeanNameAutoProxyCreator
在工作时会确保容器中符合这些名称通配符的bean
被创建代理。BeanNameAutoProxyCreator
并不会为这些需要创建代理的bean
包裹任何bean
专属的拦截器,而只会包裹容器中能找得到的通用拦截器(参考基类AbstractAutoProxyCreator
的实现逻辑)。
源代码
源代码版本 : spring-aop-5.1.5.RELEASE
package org.springframework.aop.framework.autoproxy;
// 省略 import 行
/**
* Auto proxy creator that identifies beans to proxy via a list of names.
* Checks for direct, "xxx*", and "*xxx" matches.
*
* For configuration details, see the javadoc of the parent class
* AbstractAutoProxyCreator. Typically, you will specify a list of
* interceptor names to apply to all identified beans, via the
* "interceptorNames" property.
*
*/
@SuppressWarnings("serial")
public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
@Nullable
private List<String> beanNames;
/**
* Set the names of the beans that should automatically get wrapped with proxies.
* A name can specify a prefix to match by ending with "*", e.g. "myBean,tx*"
* will match the bean named "myBean" and all beans whose name start with "tx".
* NOTE: In case of a FactoryBean, only the objects created by the
* FactoryBean will get proxied. This default behavior applies as of Spring 2.0.
* If you intend to proxy a FactoryBean instance itself (a rare use case, but
* Spring 1.2's default behavior), specify the bean name of the FactoryBean
* including the factory-bean prefix "&": e.g. "&myFactoryBean".
* 设定需要创建代理的bean的名称通配符
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.BeanFactory#FACTORY_BEAN_PREFIX
*/
public void setBeanNames(String... beanNames) {
Assert.notEmpty(beanNames, "'beanNames' must not be empty");
this.beanNames = new ArrayList<>(beanNames.length);
for (String mappedName : beanNames) {
this.beanNames.add(StringUtils.trimWhitespace(mappedName));
}
}
/**
* Identify as bean to proxy if the bean name is in the configured list of names.
*/
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
if (this.beanNames != null) {
for (String mappedName : this.beanNames) {
if (FactoryBean.class.isAssignableFrom(beanClass)) {
// 对 FactoryBean 的特殊处理
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
// 如果当前 bean 是一个 FactoryBean,但是当前bean名称通配符 mappedName 不是以 & 开头,
// 则表明该 FactoryBean 和 mappedName 不匹配,所以直接跳过
continue;
}
// 当前 bean 是一个 FactoryBean,并且 mappedName 以 & 开头,
// 那么现在对 mappedName 做一个处理 : 去掉头部的 & ,使用剩下的部分去做匹配检查
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
// 这里不管当前 bean 是否是 FactoryBean ,都有可能被执行到
// 因为此时 mappedName 已经被处理过,只需要根据 mappedName 和 beanName
// 是否匹配决定是否需要为当前bean创建代理了
if (isMatch(beanName, mappedName)) {
// 返回 [], 表示需要创建代理,但是没有bean专属拦截器
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
BeanFactory beanFactory = getBeanFactory();
if (beanFactory != null) {
// 对 bean 有别名情况的处理
String[] aliases = beanFactory.getAliases(beanName);
for (String alias : aliases) {
if (isMatch(alias, mappedName)) {
// 返回 [], 表示需要创建代理,但是没有bean专属拦截器
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
}
}
}
// 返回 null , 不要为当前bean创建代理,因为它的名称不匹配任何一个当前APC的名称通配符
return DO_NOT_PROXY;
}
/**
* Return if the given bean name matches the mapped name.
* The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
* as well as direct equality. Can be overridden in subclasses.
* @param beanName the bean name to check
* @param mappedName the name in the configured list of names
* @return if the names match
* @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)
*/
protected boolean isMatch(String beanName, String mappedName) {
return PatternMatchUtils.simpleMatch(mappedName, beanName);
}
}