文章目录:Spring源码深度解析:文章目录
Aop 即面向切面编程,而 Aspect 是Aop 思想的一种实现。
并不是所有的AOP框架都相同,它们在连接点模型上可能有强弱之分,有些允许在字段修饰符级别的应用通知,有些只支持方法调用相关的连接点。需要注意的是 Spring 只支持方法级别的连接点。
Spring 提供了4种类型的AOP支持
本文分析的是 基于 @Aspect 注解的 Aop 源码。
AspectJ 是一套AOP框架,是对java语言语法和语义的扩展,所以他自己提供了一套关键字,这也就是说,如果在没有安装 AspectJ的情况下,是无法使用 AspectJ 的。而Spring Aop 依赖的是Spring,仅仅能做到方法级别的拦截。所以在Spring中使用 @Aspect 注解实现的AOP 功能,其底层实现还是 Spring Aop。
在使用AspectJ AOP 功能时,我们需要使用注解@EnableAspectJAutoProxy(proxyTargetClass = true)
来开启Aop功能。那么我们的分析入口自然是从这个注解开始。
但实际上,启用AOP功能并不需要我们手动去声明。因为在只要我们引入了 SpringAop 对应的依赖,Spring就自动帮我们启用 Aop功能。其原因在 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
类中,如下,Spring 会将 AopAutoConfiguration
加载作为配置类,其内部类也会加载,默认加载 CglibAutoProxyConfiguration。CglibAutoProxyConfiguration
上有 @EnableAspectJAutoProxy(proxyTargetClass = true)
注解,也就达到了默认开始AOP的功能。不过我们可以通过 spring.aop.auto=false
来关闭 Spring 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)
// 启用了 AspectJ 自动代理
@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
注解。
EnableAspectJAutoProxy#AspectJAutoProxyRegistrar()
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
// 是否代理目标对象:即是否使用cglib 代理
boolean proxyTargetClass() default false;
// 是否暴露代理对象
boolean exposeProxy() default false;
}
分析了这么久的源码,从上面我们可以看到@EnableAspectJAutoProxy
注解 中使用了 @Import(AspectJAutoProxyRegistrar.class)
注解引入了AspectJAutoProxyRegistrar
类,因此我们下面来看看AspectJAutoProxyRegistrar
类的实现。
AspectJAutoProxyRegistrar
实现了ImportBeanDefinitionRegistrar
接口,那么我们自然要看看他的registerBeanDefinitions
方法了,registerBeanDefinitions
方法的作用是在Spring进入下一步动作之前可以添加BeanDefinition
,而Spring Aop 在这里将会将自动代理创建器AbstractAutoProxyCreator
添加到Spring容器中,AbstractAutoProxyCreator
是Spring 实现Aop的核心类。(Spring 在ConfigurationClassPostProcessor
中完成了对 ImportBeanDefinitionRegistrar
接口的处理,主要功能还是将BeanDefinition
保存,等待Spring解析加载到容器中。具体可以看 :Spring源码深度解析:六、ConfigurationClassPostProcessor。
下面直接来看AspectJAutoProxyRegistrar#registerBeanDefinitions()
方法 如下:
AspectJAutoProxyRegistrar#registerBeanDefinitions()
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 如有必要,注册AspectJ注释自动代理创建器。这里注册的自动代理创建器Aop实现的核心
// 这里之所以说如有必要,是因为在调用该方法时,容器中可能已经创建了一个自动代理创建器,
// 如果这个自动代理创建器优先级更高或者与当前需要创建的自动代理创建器是同一类型,则不需要创建。
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()
方法。
我们下面来看一下AopConfigUtils#registerOrEscalateApcAsRequired()
方法的实现。
AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
AopConfigUtils#registerOrEscalateApcAsRequired()
// 保存候选的自动代理创建器集合。
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
@Nullable
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 集合的顺序
* @param registry
*/
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,在 Aop 场景下,Bean 类型为AnnotationAwareAspectJAutoProxyCreator
。到这里我们就可以知道Aop的功能完成肯定是在AnnotationAwareAspectJAutoProxyCreator
中完成的,因此下面我们开始分析AnnotationAwareAspectJAutoProxyCreator
的代码。
注:
这里之所以beanName (AUTO_PROXY_CREATOR_BEAN_NAME)
和bean
的类型并不相同,是因为这个beanName
特指内部的自动代理创建器,但是自动创建代理器会对应多种不同的实现方式。比如在默认的事务中,注入的bean
类型却为InfrastructureAdvisorAutoProxyCreator
,而AOP的实现却是 AnnotationAwareAspectJAutoProxyCreator
。之所以注册不同是因为实现功能上的区别。对于事务的自动代理创建器来说,他只需要扫描被事务注解修饰的方法,并进行代理。而Spring Aop 则需要根据@PointCut
注解 来动态的解析代理哪些方法。
关于优先级的问题,我们可以看到APC_PRIORITY_LIST
集合的顺序,下标越大,优先级越高。因此可以得知优先级的顺序应该是
InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator
由于本文主要分析的是Spring Aop
的过程,所以我们下面还是对 AnnotationAwareAspectJAutoProxyCreator
自动代理创建器进行分析。AnnotationAwareAspectJAutoProxyCreator
本身的逻辑并不多,核心逻辑在其父类AbstractAutoProxyCreator
中。
上面我们可以看到,整个过程就是将AnnotationAwareAspectJAutoProxyCreator
注册到 Spring 中并且设置一些属性。
那么我们来看看 AnnotationAwareAspectJAutoProxyCreator
,其主要逻辑实际上还是在其父类AbstractAutoProxyCreator
中完成。(包括事务的实现逻辑也主要在 AbstractAutoProxyCreator
中,这一点后续关于事务的源码分析: Spring源码分析十四:事务实现① - AutoProxyRegistrar)
AnnotationAwareAspectJAutoProxyCreator
实现了SmartInstantiationAwareBeanPostProcessor
接口的方法,SmartInstantiationAwareBeanPostProcessor
接口方法穿插在Bean
初始化的过程中,转念一想,Spring Aop
的核心思想就是动态代理,那么必然会在bean初始化的时候"做手脚"。因此我们下面的重心就放在 SmartInstantiationAwareBeanPostProcessor
的方法分析上。
注:关于 后处理器SmartInstantiationAwareBeanPostProcessor
的内容 具体请参考 Spring源码深度解析:十二、后处理器 BeanPostProcessor
上面也说了,其主要逻辑在AbstractAutoProxyCreator
中实现,这里是在AbstractAutoProxyCreator
中实现的SmartInstantiationAwareBeanPostProcessor
方法,所以我们下面看的实际是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) throws BeansException {
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
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.
// 正常来说Aop的代理创建应当在Bean 创建后再进行代理类,但是这里在Bean创建前就可能进行了代理:
// 对此,官方注释解释: 如果我们有自定义的TargetSource,请在此处创建代理。抑制目标Bean的不必要的默认实例化:
// TargetSource将以自定义方式处理目标实例。
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 postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, 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) throws BeansException {
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
方法中。但是在此之前,需要先判断一下当前bean是否需要代理,而这个判断应该在Bean 创建之前进行,即在postProcessBeforeInstantiation
方法中。我们可以看到关键方法是在于wrapIfNecessary
。
不过在此之前我们先来看看postProcessBeforeInstantiation
方法中的一段分析。
实际上,并非所有满足织入条件的Bean 都会被代理。基础设施类无法代理,自身也无法代理自身。
我们这一部分主要是用来分析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则不需要代理。
我们可以看到关键的判断条件就是下面两个:
这里我们可以很清楚的看到,如果当前bean是基础类(Advice
、Pointcut
、Advisor
、AopInfrastructureBean
及其子类),则返回true。
AbstractAutoProxyCreator#isInfrastructureClass(Class> beanClass)
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;
}
AspectJAwareAdvisorAutoProxyCreator#shouldSkip(Class> beanClass, String 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;
}
}
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
。即自身不能代理自身。
综上,跳过Aop代理的条件就是:Aop基础设施类或者 代理自身时 会跳过代理
上面一步是强行跳过了一部分不能代理的Bean,如果到达这一步说明当前Bean不需要跳过代理,那么则需要判断当前Bean是否满足代理条件。
postProcessAfterInitialization()
方法中我们可看到关键方法wrapIfNecessary
。
wrapIfNecessary
主要是用来判断当前bean是否需要代理,如果需要,则进行bean封装。
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果当前bean已经处理过了直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 无需增强。这个在AbstractAutoProxyCreator#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);
// DO_NOT_PROXY = null。很明显,即使当前Bean 需要进行代理,如果没有增强方法也没必要进行代理
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);
需要注意的是,上面两句关键语句,在AbstractAutoProxyCreator#postProcessBeforeInstantiation()
中也有过调用
篇幅所限,新开文章:Spring源码分析十五:@Aspect方式的AOP中篇 - getAdvicesAndAdvisorsForBean
篇幅所限,新开文章: Spring源码深度解析十六:@Aspect方式的AOP 下篇 - createProxy
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即一个增强操作,一个Advisor包含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方法中完成。