文章目录
一、前言
本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。在阅读过程中也创建了一些衍生文章,衍生文章的意义是因为自己在看源码的过程中,部分知识点并不了解或者对某些知识点产生了兴趣,所以为了更好的阅读源码,所以开设了衍生篇的文章来更好的对这些知识点进行进一步的学习。
全集目录:Spring源码分析:全集整理
本文系列:
Spring源码分析十一:@Aspect方式的AOP上篇 - @EnableAspectJAutoProxy
Spring源码分析十二:@Aspect方式的AOP中篇 - getAdvicesAndAdvisorsForBean
Spring源码分析十三:@Aspect方式的AOP下篇 - createProxy
本文衍生篇:
Spring 源码分析衍生篇九 : AOP源码分析 - 基础篇
二、简介
Aop 即面向切面编程,而 Aspect 是Aop 思想的一种实现。
并不是所有的AOP框架都相同,它们在连接点模型上可能有强弱之分,有些允许在字段修饰符级别的应用通知,有些只支持方法调用相关的连接点。需要注意的是 Spring 只支持方法级别的连接点。
Spring 提供了4种类型的AOP支持
- 基于代理的经典Spring Aop
- 纯Pojo切面
- @Aspect注解驱动的切面
- 注入式的Aspectj的切面
前三种都是Spring Aop 实现的变体,Spring Aop 构建在动态代理之上,因此Spring 对Aop的支持局限于方法拦截。
本文分析的是 基于 @Aspect 注解的 Aop 源码。
1. Spring Aop 和 AspectJ 的关系
AspectJ 是一套AOP框架,是对java语言语法和语义的扩展,所以他自己提供了一套关键字,这也就是说,如果在没有安装 AspectJ的情况下,是无法使用 AspectJ 的。而Spring Aop 依赖的是Spring,仅仅能做到方法级别的拦截。所以在Spring中使用 @Aspect 注解实现的AOP 功能,其底层实现还是 Spring Aop。
2. @ApsectJ 的启用 - @EnableAspectJAutoProxy
在使用AspectJ AOP 功能时,我们需要使用注解 @EnableAspectJAutoProxy(proxyTargetClass = true)
来开启Aop 功能。那么我们的分析入口自然是从这个注解开始。
但实际上,启用AOP功能并不需要我们手动去声明。因为在只要我们引入了 SpringAop 对应的依赖,Spring就自动帮我们启用 Aop功能。其原因在 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
类中,如下,Spring 会将 AopAutoConfiguration
加载作为配置类,其内部类也会加载,默认加载 CglibAutoProxyConfiguration
。CglibAutoProxyConfiguration
上有 @EnableAspectJAutoProxy(proxyTargetClass = true)
注解,也就达到了默认开始AOP的功能。
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration {
ClassProxyingConfiguration(BeanFactory beanFactory) {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
}
}
不过我们仍旧可以知道,AOP的功能入口在于@EnableAspectJAutoProxy
注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
分析了这么久的源码,从上面我们可以看到 @EnableAspectJAutoProxy
注解 中使用了 @Import(AspectJAutoProxyRegistrar.class)
注解引入了AspectJAutoProxyRegistrar
类,因此我们下面来看看 AspectJAutoProxyRegistrar
类的实现。
二、 AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrar
实现了 ImportBeanDefinitionRegistrar
接口,那么我们自然要看看他的registerBeanDefinitions
方法了。(Spring 在 ConfigurationClassPostProcessor 中完成了对 ImportBeanDefinitionRegistrar 接口的处理,主要功能还是将BeanDefinition注入到Spring容器中。具体可以看 :Spring 源码分析衍生篇七 :ConfigurationClassPostProcessor 上篇)。
/**
* 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) {
// 如有必要,注册Aspect J注释自动代理创建器
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 获取 @EnableAspectJAutoProxy 注解
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
// 解析 proxyTargetClass 属性
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 解析 exposeProxy 属性
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
从上面代码我们可以看到,registerBeanDefinitions
方法最主要的功能就是自动代理创建器的注册。(所谓的自动代理创建器,顾名思义就是可以用来自动创建代理的"机器",可以简单理解成Spring 封装的一个创建代理对象的工具类,具有多种实现方式,这个下面会讲。这里使用AOP的实现方式,因此我们来看他的注册过程, 即 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
方法 。
其中 registerAspectJAnnotationAutoProxyCreatorIfNecessary
方法在经历数次跳转后最终调用了 AopConfigUtils#registerOrEscalateApcAsRequired
方法。
上面我们说到自动代理创建器有多种实现方式,但是实际使用只能选择其中一种,所以需要根据优先级来判断使用哪一种。
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
// Set up the escalation list...
// 事务使用
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
// Spring aop 使用
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
// 这里的 cls 是 AnnotationAwareAspectJAutoProxyCreator.class
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果有注册,则判断优先级,将优先级的高的保存
// 如果已经纯在了自动代理创建器,且存在的自动代理创建器与现在的并不一致,那么需要根据优先级来判断到底要使用哪个
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
// 改变bean所对应的className 属性
apcDefinition.setBeanClassName(cls.getName());
}
}
// 如果已经存在自动代理创建器,并且与将要创建的一致,那么无需再次创建
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
...
// 可以看到,所谓的优先级顺序实际上是在 APC_PRIORITY_LIST 集合的顺序
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 设置 proxyTargetClass 属性
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
...
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 设置 exposeProxy 属性
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
这里可以看到,整体是注册了一个beanName为“org.springframework.aop.config.internalAutoProxyCreator”
的bean,Bean 类型为 AnnotationAwareAspectJAutoProxyCreator
。到这里我们就可以知道Aop的功能完成肯定是在 AnnotationAwareAspectJAutoProxyCreator
中完成的,因此下面我们开始分析 AnnotationAwareAspectJAutoProxyCreator
的代码。
注:
-
这里之所以 beanName (
AUTO_PROXY_CREATOR_BEAN_NAME
) 和 bean的类型并不相同,是因为这个beanName 特指内部的自动代理创建器
,但是自动创建代理器会对应多种不同的实现方式。比如在默认的事务中,注入的bean类型却为InfrastructureAdvisorAutoProxyCreator
,而AOP的实现却是AnnotationAwareAspectJAutoProxyCreator
。 -
关于优先级的问题,我们可以看到
APC_PRIORITY_LIST
集合的顺序,下标越大,优先级越高。因此可以得知优先级的顺序应该是
InfrastructureAdvisorAutoProxyCreator
<AspectJAwareAdvisorAutoProxyCreator
<AnnotationAwareAspectJAutoProxyCreator
三、AnnotationAwareAspectJAutoProxyCreator
上面我们可以看到,整个过程就是将 AnnotationAwareAspectJAutoProxyCreator
注册到 Spring 中并且设置一些属性。
那么我们来看看 AnnotationAwareAspectJAutoProxyCreator
,其主要逻辑实际上还是在其父类 AbstractAutoProxyCreator
中完成。(包括事务的实现逻辑也主要在 AbstractAutoProxyCreator
中,这一点后续关于事务的源码分析会详细解读)
AnnotationAwareAspectJAutoProxyCreator
实现了 SmartInstantiationAwareBeanPostProcessor
接口的方法,SmartInstantiationAwareBeanPostProcessor
接口方法穿插在 Bean初始化的过程中,转念一想,Spring Aop的核心思想就是动态代理,那么必然会在bean初始化的时候"做手脚"。因此我们下面的重心就放在 SmartInstantiationAwareBeanPostProcessor
的方法分析上。
注:关于 后处理器SmartInstantiationAwareBeanPostProcessor
的内容 具体请参考 Spring源码分析衍生篇四:后处理器 BeanPostProcessor。
上面也说了,其主要逻辑在AbstractAutoProxyCreator
中实现,这里是在AbstractAutoProxyCreator
中实现的 SmartInstantiationAwareBeanPostProcessor
方法,所以我们下面看的实际是 AbstractAutoProxyCreator
类,
四、AbstractAutoProxyCreator
这里额外提一下,Spring事务的实现也依赖于 AbstractAutoProxyCreator
类,并且逻辑与Aop 的实现基本一致,因为事务的实现的方式也是Aop代理。后面新篇讲到事务时会相信解读。
下面是AbstractAutoProxyCreator
中 SmartInstantiationAwareBeanPostProcessor
的一些实现方法的实现
@Override
@Nullable
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
// 从代理换缓存中获取代理类型
if (this.proxyTypes.isEmpty()) {
return null;
}
Object cacheKey = getCacheKey(beanClass, beanName);
return this.proxyTypes.get(cacheKey);
}
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 是基础设施类 || 是被 @Aspect 注解修饰的类。则跳过 Aop代理
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 获取代理增强点
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 创建代理类
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
我们可以根据 SmartInstantiationAwareBeanPostProcessor
方法的调用顺序进行分析。如果想要生成代理,可以在bean初始化之后。也就是 postProcessBeforeInstantiation
方法中。在 postProcessBeforeInstantiation
方法中我们可以看到关键方法是在于 wrapIfNecessary
。不过在此之前我们先来看看 postProcessBeforeInstantiation
方法中的一段分析
1. 是否跳过代理
我们这一部分主要是用来分析AbstractAutoProxyCreator#postProcessBeforeInstantiation
中的这一段代码:
// 是基础设施类 || 是被 @Aspect 注解修饰的类。则跳过 Aop代理
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
这段代码将在bean加载前判断bean是否交由Aop代理,亦或者换一种说法 : 判断将该Bean交由Spring容器创建还是交由Aop 创建。在实际创建bean代理时候,Spring会根据cacheKey 获取到值,为false则不需要代理。
我们可以看到关键的判断条件就是下面两个:
1.1. isInfrastructureClass(beanClass)
这里我们可以很清楚的看到,如果当前bean是基础类(Advice
、Pointcut
、Advisor
、AopInfrastructureBean
及其子类),则返回true。
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
1.2. shouldSkip(beanClass, beanName)
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
// 寻找所有候选代理增强点。关于这个方法,在后面关于 getAdvicesAndAdvisorsForBean 的文章中会详细分析,这里就不分析
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 从前面的代码分析可以看出,如果是Aop 的动态封装都是基于 InstantiationModelAwarePointcutAdvisorImpl 也就是 InstantiationModelAwarePointcutAdvisor,自然是继承PointcutAdvisor
// 如果 代理类基于 AspectJPointcutAdvisor && aspectName==beanName,即当前初始化的类是ApspectJ类本身。则返回true,跳过代理
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
// 父类shouldSkip 判断了文件是否是 .ORIGINAL 后缀,是则跳过。
return super.shouldSkip(beanClass, beanName);
}
关于if语句判断条件:
-
advisor instanceof AspectJPointcutAdvisor
基础篇有讲过。Advisor
两个子接口PointcutAdvisor
、IntroductionAdvisor
。IntroductionAdvisor与PointcutAdvisor
最本质上的区别就是,IntroductionAdvisor
只能应用于类级别的拦截,只能使用Introduction型的Advice。而不能像PointcutAdvisor
那样,可以使用任何类型的Pointcut,以及几乎任何类型的Advice。而通过 Spring Aop 动态注入的是 Advisor 默认都是
InstantiationModelAwarePointcutAdvisorImpl
都满此条件。所以这里为false 的情况只有硬编码注入时IntroductionAdvisor
类型的Advisor
,所以这里基本都会返回true。 -
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName))
: 这里就是判断beanName 是否是 @Aspect 注解修饰的bean的name。那么就可以看出,这里返回ture的条件是 @Apsect 修饰的 AspectJPointcutAdvisor 类。即 被 @ApsectJ 修饰的类会跳过代理
综上,跳过Aop代理的条件就是:Aop基础设施类或者 被@Aspect修饰的类
2. AbstractAutoProxyCreator#wrapIfNecessary
postProcessAfterInitialization
方法中我们可看到关键方法 wrapIfNecessary。
wrapIfNecessary
主要是用来判断当前bean是否需要代理,如果需要,则进行bean封装。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果已经处理过
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 无需增强。这个在postProcessBeforeInstantiation 方法中对 cacheKey 进行了判断缓存,this.advisedBeans.get(cacheKey) 的返回值代表当前bean是否需要aop代理。
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 给定的bean类是否是一个基础设施类(Advice、Pointcut、Advisor、AopInfrastructureBean) || 配置了指定bean不需要进行代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 如果不需要代理,则记录下来
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 如果存在增强方法则创建代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
可以很明显的发现下面两个方法是关键。
// 获取适配的增强点
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 根据增强点创建对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
2.1. 获取代理增强点 - getAdvicesAndAdvisorsForBean
篇幅所限,新开文章:Spring源码分析十二:@Aspect方式的AOP中篇 - getAdvicesAndAdvisorsForBean
2.2. 创建代理类 - createProxy
篇幅所限,新开文章: Spring源码分析十三:@Aspect方式的AOP 下篇 - createProxy
五、Spring Aop总结
1. @EnableAspectJAutoProxy (proxyTargetClass = true)开始Aop功能。实际上在引入aspectj包之后, Spring默认会通过AopAutoConfiguration配置类开启AOP功能
2. @EnableAspectJAutoProxy (proxyTargetClass = true)注解通过@Import(AspectJAutoProxyRegistrar.class)引入了AspectJAutoProxyRegistrar类
3. AspectJAutoProxyRegistrar中注册了自动代理创建器AnnotationAwareAspectJAutoProxyCreator。之后的操作都在AnnotationAwareAspectJAutoProxyCreator中进行。
4. AnnotationAwareAspectJAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口, 所以会在Bean创建的时候,
发现并记录了合适的所有的Advisor并进行拦截代理。
4.1. 发现所有的Advisor : 这里分为两步。
第一步是扫描BeanFactory中的所有Advisor类型的bean。这里直接通过BeanFactory获取即可。假设这里获取到的Advisor集合为Advisors1。
第二步则是通过扫描@Aspect注解找到切面类,随后筛选切面类中的方法。找到被@Around、@Before等注解修饰的通知(Advice) 进行解析,
并封装成不同的Advice类型(这里不包括@Pointcut注解的解析), @Pointcut会被解析成切入点(Pointcut类)。
随后Advice和Pointcut会被一起封装成一个Advisor (顾问,也即是Advisor) 。
也就是说,在这里Spring封装出了Pointcut类(实际上是AspectJExpressionPointcut)和
Advice类(这里的Advice根据注解使用的不同分为多个种类,如AspectJAroundAdvice、AspectJMethodBeforeAdvice等)以及
包含他俩的Advisor(实际上是InstantiationModelAwarePointcutAdvisorImpl)。
这个过程是在ReflectiveAspectJAdvisorFactory#getAdvisor和InstantiationModelAwarePointcutAdvisorImpl构造函数中完成的。
这里就动态解析出了@Aspect 注解下的切入点,并被封装成了Advisor集合。假设这里的Advisor集合为Advisors2。
这两步结束后,就解析出来了当前所有的Advisors =Advisors1 + Advisors2;
注:可以简单的理解为一个Advisor即一个增强操作,一个Adviso包含Advice和Pointcut。
Advice定义了具体增强操作,如前置,后置,环绕等,
Pointcut定义了织入规则,满足规则的bean方法才能被增强。
4.2. 筛选所有合适的Advisor:上一-步筛选出来的Advisor可能并不适用于当前bean,所以需要筛选出合适于当前bean的Advisor。
比如@Pointcut ("execution (* com.demo.service.impl.UserServiceImpl.findAll())");切入的是UserServiceImpl,而当前的bean如果是
RoleServiceImpl就不应该被此Advisor所增强。
5. 第四步结束后,这里已经筛选出来了适合当前bean所使用的Advisor,下面需要创建代理类。创建代理则是委托给了ProxyFactory来完成。
ProxyFactory 使用 Advisor 中的 Advice 创建出来了代理增强类并注入到Spring容器中。
ProxyFactory中有筛选出来的Advisor集合,即Advisors。
ProxyFactory根据情况选择Jdk代理(JdkDynamicAopProxy)或者Cglib代理(ObjenesisCglibAopProxy)来完成创建代理类的操作。
最终执行的代理方法,实际上都是MethodInterceptor#invoke方法。
这里需要注意的是:对于AspectJAroundAdvice、AspectJAfterThrowingAdvice他们直接实现了MethodInterceptor接口,所以可以直接使用,
但是对于AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice则需要进行一个适配。
这个适配的是在创建代理类的过程中。在AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice方法中完成。
至此,@Aspect方式的AOP 的源码分析结束。
以上:内容部分参考
《Spring实战》
《Spring源码深度解析》
https://www.cnblogs.com/cheng21553516/p/12190008.html
https://blog.csdn.net/wyl6019/article/details/80136000
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正