抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

SpringAOP-注解解析

前言

​ 上文介绍了 AOP 的基本概念,本文开始进入 AOP 的源码解析,本文仍以 AspectJ 来进行介绍,首先是 AOP 注解的解析。

​ 在使用ApplicationContext相关实现类加载bean的时候,会针对所有单例且非懒加载的bean,在构造ApplicationContext的时候就会创建好这些bean,而不会等到使用的时候才去创建。这也就是单例bean默认非懒加载的应用

​ 读者需要了解BeanPostProcessor的相关使用,所有实现BeanPostProcessor接口的类,在初始化bean的时候都会调用这些类的方法,一般用于在bean初始化前或后对bean做一些修改。而AOP的功能实现正式基于此,在bean初始化后创建针对该bean的proxy,然后返回给用户该proxy

​ 结合以上两点,被代理后的bean,实际在ApplicationContext构造完成之后就已经被创建完成,getBean()的操作直接从singletonObjects中获取即可

AOP解析类

我们知道Spring的所有类或者注解都需要解析类来处理,Spring对AOP的解析类在哪里呢

XML解析类

XML方式是通过<aop:aspectj-autoproxy />配置来进行配置的,很明显是一个自定义注解

解开启 AOP 功能时,Spring会从“META-INF/spring.handlers” 配置文件中拿到该注解对应的 NamespaceHandlerSupport:AopNamespaceHandler

在 AopNamespaceHandler 的 init 方法会给该注解注册对应的解析器,aspectj-autoproxy 对应的解析器是:AspectJAutoProxyBeanDefinitionParser。

1
2
3
4
5
6
7
8
9
10
11
12
public class AopNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
//对aspectj-autoproxy配置的解析类
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());
}
}

我们知道,当解析到 <aop:aspectj-autoproxy /> 注解时,会调用 AspectJAutoProxyBeanDefinitionParser 的 parse方法,关于自定义注解的解析内容之前 IoC 的文章介绍过了。

AspectJAutoProxyBeanDefinitionParser#parse
1
2
3
4
5
6
7
8
9
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 1.注册AspectJAnnotationAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 2.对于注解中子节点的处理
extendBeanDefinition(element, parserContext);
return null;
}
registerAspectJAnnotationAutoProxyCreatorIfNecessary

注册AspectJAnnotationAutoProxyCreator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 注册AspectJAnnotationAutoProxyCreator
*
* @param parserContext
* @param sourceElement
*/
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 1.注册AspectJAnnotationAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 2.对于proxy-target-class以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 3.注册组件并通知,便于监听器做进一步处理
registerComponentIfNecessary(beanDefinition, parserContext);
}
registerAspectJAnnotationAutoProxyCreatorIfNecessary
1
2
3
4
5
6
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {

return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
registerOrEscalateApcAsRequired
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 1.如果注册表中已经存在beanName=org.springframework.aop.config.internalAutoProxyCreator的bean,则按优先级进行选择。
// beanName=org.springframework.aop.config.internalAutoProxyCreator,可能存在的beanClass有三种,按优先级排序如下:
// InfrastructureAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 拿到已经存在的bean定义
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 如果已经存在的bean的className与当前要注册的bean的className不相同,则按优先级进行选择
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 拿到已经存在的bean的优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
// 拿到当前要注册的bean的优先级
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
// 如果当前要注册的bean的优先级大于已经存在的bean的优先级,则将bean的className替换为当前要注册的bean的className,
apcDefinition.setBeanClassName(cls.getName());
}
// 如果小于,则不做处理
}
// 如果已经存在的bean的className与当前要注册的bean的className相同,则无需进行任何处理
return null;
}

// 2.如果注册表中还不存在,则新建一个Bean定义,并添加到注册表中
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// 设置了order为最高优先级
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册BeanDefinition,beanName为org.springframework.aop.config.internalAutoProxyCreator
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}

org.springframework.aop.config.internalAutoProxyCreator 是内部管理的自动代理创建者的 bean 名称,可能对应的 beanClassName 有三种,对应的注解如下:

InfrastructureAdvisorAutoProxyCreator:<tx:annotation-driven />

AspectJAwareAdvisorAutoProxyCreator:<aop:config />

AnnotationAwareAspectJAutoProxyCreator:<aop:aspectj-autoproxy />

当同时存在多个注解时,会使用优先级最高的 beanClassName 来作为 org.springframework.aop.config.internalAutoProxyCreator 的 beanClassName。本系列文章暂不考虑同时存在其他注解的情况,所以在这边会注册的 beanClassName 为:AnnotationAwareAspectJAutoProxyCreator。

useClassProxyingIfNecessary
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
// 如果节点设置了proxy-target-class=true,则给beanName为org.springframework.aop.config.internalAutoProxyCreator
// 的BeanDefinition添加proxyTargetClass=true的属性,之后创建代理的时候将强制使用Cglib代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
// 如果节点设置了expose-proxy=true,则给beanName为org.springframework.aop.config.internalAutoProxyCreator
// 的BeanDefinition添加exposeProxy=true的属性,之后创建拦截器时会根据该属性选择是否暴露代理类
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}

注解类解析

注解方式是在spring能扫描到的类中增加@EnableAspectJAutoProxy注解

1
2
3
4
@Component
@EnableAspectJAutoProxy
public class EnabledAOP {
}
@EnableAspectJAutoProxy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*
* true
* 1、目标对象实现了接口 – 使用CGLIB代理机制
* 2、目标对象没有接口(只有实现类) – 使用CGLIB代理机制
*
* false
* 1、目标对象实现了接口 – 使用JDK动态代理机制(代理所有实现了的接口)
* 2、目标对象没有接口(只有实现类) – 使用CGLIB代理机制
*/
boolean proxyTargetClass() default false;

/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;

}

我们发现该类主要是通过@Import注解导入了AspectJAutoProxyRegistrar.class 的类

AspectJAutoProxyRegistrar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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) {

// 1.注册AspectJAnnotationAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
//2. 找到类导入类中的@EnableAspectJAutoProxy注解
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
//如果不为空
if (enableAspectJAutoProxy != null) {
//3. 设置proxyTargetClass属性
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//4. 设置exposeProxy属性
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
registerAspectJAnnotationAutoProxyCreatorIfNecessary
1
2
3
4
5
6
7
8
9
10
11
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {

return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

然后就进入了注册的核心方法registerOrEscalateApcAsRequired

总结

​ 本文的内容比较简单,最重要的内容就是注册了内部管理的自动代理创建者的 bean:AnnotationAwareAspectJAutoProxyCreator,AOP 的大部分重要内容都在这个bean 里,之后会一一介绍。

评论