Spring AOP: APC 注册器 AutoProxyRegistrar

AutoProxyRegistrar作为ImportBeanDefinitionRegistrar的一种实现,用于检测导入者类上的注解是否包含mode和proxyTargetClass属性。若属性存在且mode设置为PROXY时,将向容器注册自动代理创建器。本文详细介绍了AutoProxyRegistrar的工作原理及应用场景。

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

概述

AutoProxyRegistrar是一个ImportBeanDefinitionRegistrar,它会检测导入者类上的某个注解是否带有属性modeproxyTargetClass,如果检测到这些属性,在modePROXY时,它会向容器注册一个自动代理创建器auto proxy creator

AutoProxyRegistrar可以被某个配置类这么使用 :

@Import(AutoProxyRegistrar.class)
// 同时该配置类还应该使用带有 mode/proxyTargetClass 属性的另外一个注解

或者类似Spring框架自身这么使用AutoProxyRegistrar :


// 1. 定义一个 AdviceModeImportSelector, 它使用到了 AutoProxyRegistrar
public class TransactionManagementConfigurationSelector extends 
                    AdviceModeImportSelector<EnableTransactionManagement> {

	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(),...};
			...
		}
	}
		...
}

// 2. 上面所定义的 TransactionManagementConfigurationSelector 被另外一个注解类所使用
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
    // ...
}

// 3. 注解类 @EnableTransactionManagement 被某个配置类所使用
@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
// ...
public static class CglibAutoProxyConfiguration {

}

AutoProxyRegistrar核心的逻辑在于其方法registerBeanDefinitions ,该方法会遍历导入者类上使用的所有注解,找到第一个带有属性mode/proxyTargetClass属性的注解,如果这些属性不为空,并且mode/proxyTargetClass属性的类型为AdviceMode/Boolean,则会在mode属性值为PROXY时,调用AopConfigUtils#registerAutoProxyCreatorIfNecessary向容器注册一个自动代理创建器auto proxy creator(可以使用缩写APC表示),实现类使用InfrastructureAdvisorAutoProxyCreator

如果AutoProxyRegistrar#registerBeanDefinitions在导入者类上的注解中找不到符合条件的mode/proxyTargetClass属性,则会输出日志 :

AutoProxyRegistrar was imported but no annotations were found having both ‘mode’ and ‘proxyTargetClass’ attributes of type AdviceMode and boolean respectively. This means that auto proxy creator registration and configuration may not have occurred as intended, and components may not be proxied as expected. Check to ensure that AutoProxyRegistrar has been @Import’ed on the same class where these annotations are declared; otherwise remove the import of AutoProxyRegistrar altogether.

源代码

源代码版本 : spring-context-5.1.5.RELEASE

package org.springframework.context.annotation;

import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

/**
 * Registers an auto proxy creator against the current BeanDefinitionRegistry
 * as appropriate based on an @Enable* annotation having mode and
 * proxyTargetClass attributes set to the correct values.
 *
 * @author Chris Beams
 * @since 3.1
 * @see EnableAspectJAutoProxy
 */
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	private final Log logger = LogFactory.getLog(getClass());

	/**
	 * Register, escalate, and configure the standard auto proxy creator (APC) against the
	 * given registry. Works by finding the nearest annotation declared on the importing
	 * @Configuration class that has both mode and proxyTargetClass
	 * attributes. If mode is set to PROXY, the APC is registered; if
	 * proxyTargetClass is set to true, then the APC is forced to use
	 * subclass (CGLIB) proxying.
	 * 
	 * Several @Enable* annotations expose both mode and
	 * proxyTargetClass attributes. It is important to note that most of these
	 * capabilities end up sharing a AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME
	 * single APC. For this reason, this implementation doesn't "care" exactly which
	 * annotation it finds -- as long as it exposes the right mode and
	 * proxyTargetClass attributes, the APC can be registered and configured all
	 * the same.
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, 
										BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
		Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
		for (String annoType : annoTypes) {
			AnnotationAttributes candidate = 
					AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
			if (candidate == null) {
				continue;
			}
			Object mode = candidate.get("mode");
			Object proxyTargetClass = candidate.get("proxyTargetClass");
			if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
					Boolean.class == proxyTargetClass.getClass()) {
				candidateFound = true;
				if (mode == AdviceMode.PROXY) {
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
		if (!candidateFound && logger.isInfoEnabled()) {
			String name = getClass().getSimpleName();
			logger.info(String.format("%s was imported but no annotations were found " +
					"having both 'mode' and 'proxyTargetClass' attributes of type " +
					"AdviceMode and boolean respectively. This means that auto proxy " +
					"creator registration and configuration may not have occurred as " +
					"intended, and components may not be proxied as expected. Check to " +
					"ensure that %s has been @Import'ed on the same class where these " +
					"annotations are declared; otherwise remove the import of %s " +
					"altogether.", name, name, name));
		}
	}

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值