Spring AOP : APC 自动代理创建器 BeanNameAutoProxyCreator

本文深入解析Spring AOP中的BeanNameAutoProxyCreator组件,它根据bean名称匹配创建代理对象。使用者通过设置bean名称通配符,确保符合规则的bean被代理。BeanNameAutoProxyCreator仅包裹通用拦截器,不添加bean专属拦截器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

BeanNameAutoProxyCreatorSpring 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);
	}

}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值