Spring AOP 浅析 — 开启aop的配置

本文详细解析了Spring中AOP的两种配置方式:注解形式和XML形式,深入探讨了@EnableAspectJAutoProxy注解及AnnotationAwareAspectJAutoProxyCreator在AOP开启过程中的关键作用。
摘要由CSDN通过智能技术生成

目录

spring开启aop的配置有两种方式

使用@EnableAspectJAutoProxy注解

使用XML中配置


以下是最近spring的学习整理,如有不对之处,欢迎大神指教!

 

spring开启aop的配置有两种方式

1、注解形式

@Configuration
@EnableAspectJAutoProxy
public class Config {

}

有效的切面类:

@Aspect
@Component
public class MyAspect {
 	//....   
}

 

2、xml形式

<aop:aspectj-autoproxy/>

<bean class = "xxx.MyAspect"/>

有效的切面类:

@Aspect
public class MyAspect {
 	//....   
}

可以看出两种方式呢,略有不同。@AspectJ 注解只能作用于Spring Bean 上面,所以你用 @Aspect 修饰的类要么是用 @Component注解修饰,要么是在 XML中配置过的。

 

使用@EnableAspectJAutoProxy注解

EnableAspectJAutoProxy

可以看到源码里面使用@Import导入了 

AspectJAutoProxyRegistrar

作用是可以在IOC容器启动时执行AspectJAutoProxyRegistrar的registerBeanDefinitions方法

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		// 注册AnnotationAwareAspectJAutoProxyCreator  TODO-1
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		//拿到EnableAspectJAutoProxy的属性 并设置proxy-target-class和 expose-proxy属性
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

}

registerBeanDefinitions方法主要做的事情就是根据EnableAspectJAutoProxy类上的属性的值注册、升级和配置AspectJ自动代理创建器。

(ps:这个类实现了ImportBeanDefinitionRegistrar接口。很多开源框架与Spring 集成的时候都扩展了这个接口,比如mybatis的MapperScannerRegistrar ) 参考https://www.logicbig.com/tutorials/spring-framework/spring-core/import-bean-registrar.html

可以看到在TODO-1这里会注册类

AnnotationAwareAspectJAutoProxyCreator

我们来看下这个类的继承关系,可以看到它其实是一个BeanPostProcessor,是不是有种豁然开朗的赶脚。

我们先回顾思考下代理模式的实现思路:(接口) + 真实实现类 + 代理类。是不是要先有了真实的实现类,才能够生成代理类?!

而 AnnotationAwareAspectJAutoProxyCreator 恰恰是一个BeanPostProcessor(原谅我又重复了一次),那就很容易联想到,Spring AOP 就是在这一步,进行代理增强

 

使用XML中配置

一般xml的配置会有一个对用的xxxHandler,那我们在源码中找到了 

public class AopNamespaceHandler extends NamespaceHandlerSupport {

	/**
	 * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
	 * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
	 * and '{@code scoped-proxy}' tags.
	 */
	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		// 自动代理
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

}
/**
 * {@link BeanDefinitionParser} for the {@code aspectj-autoproxy} tag,
 * enabling the automatic application of @AspectJ-style aspects found in
 * the {@link org.springframework.beans.factory.BeanFactory}.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @since 2.0
 */
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {

	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		//注册AnnotationAwareAspectJAutoProxyCreator
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		extendBeanDefinition(element, parserContext);
		return null;
	}

	private void extendBeanDefinition(Element element, ParserContext parserContext) {
		BeanDefinition beanDef =
				parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
		if (element.hasChildNodes()) {
			addIncludePatterns(element, parserContext, beanDef);
		}
	}

	private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
		ManagedList<TypedStringValue> includePatterns = new ManagedList<>();
		NodeList childNodes = element.getChildNodes();
		for (int i = 0; i < childNodes.getLength(); i++) {
			Node node = childNodes.item(i);
			if (node instanceof Element) {
				Element includeElement = (Element) node;
				TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
				valueHolder.setSource(parserContext.extractSource(includeElement));
				includePatterns.add(valueHolder);
			}
		}
		if (!includePatterns.isEmpty()) {
			includePatterns.setSource(parserContext.extractSource(element));
			beanDef.getPropertyValues().add("includePatterns", includePatterns);
		}
	}

}
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
		//注册AnnotationAwareAspectJAutoProxyCreator
		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		//对proxy-target-class和 expose-proxy属性的处理
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}

可以看到xml方式的也会去注册AnnotationAwareAspectJAutoProxyCreator这个类。

 

两种开启aop的方式虽然不同,但是最终都是由AnnotationAwareAspectJAutoProxyCreator这个类来实现的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值