目录
以下是最近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这个类来实现的