文章目录
前言
AOP面向切面编程,用于为一批目标方法(JoinPoint)配置增强方法(Advice)来实现切面。Advice通过PointCut(一个表达式)匹配目标方法(JoinPoint)。应用层面可以通过配置文件和注解两种方式创建Advice和PointCut。这次只分析@Aspect注解方式。
一、AOP的应用Demo
下面是在SpringBoot项目中,基于注解对AOP的使用
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
application.yml配置文件
spring:
aop:
proxy-target-class: false
动态代理JDK的比较熟悉,将默认的CGLIB改为JDK。方便后续源码分析说明
目标方法类
package com.example.demo.service.impl;
@Service
public class JoinPointService implements JoinPointServiceI {
//这个方法就是一个JoinPoint
@Override
public void doSome1(String a) {
System.out.println("JoinPoint-doSome1:"+ "["+a+"]");
}
}
增强方法和切入点
@Aspect
@Component
public class PointCutHandle {
//这里就是PointCut 用于与目标方法匹配
@Pointcut("execution(public * com.example.demo.service.impl.*.*(..))")
public void pointcut(){}
//前置增强方法 Advice
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
System.out.println("before : " + Arrays.toString(joinPoint.getArgs()));
}
//后置增强方法 Advice
@AfterReturning("pointcut()")
public void afterReturning(JoinPoint joinPoint) {
System.out.println("afterReturning : " + Arrays.toString(joinPoint.getArgs()));
}
//最终后置增强方法 Advice
@After("pointcut()")
public void after(JoinPoint joinPoint) {
System.out.println("after : " + Arrays.toString(joinPoint.getArgs()));
}
}
常用的有5种Advice,这里列出了3种
测试类
@SpringBootTest
class DemoApplicationTests {
@Autowired
private JoinPointServiceI joinPointService;
@Test
void contextLoads() {
joinPointService.doSome1("9981");
}
}
最终执行结果
before : [9981]
JoinPoint-doSome1:[9981]
afterReturning : [9981]
after : [9981]
Demo中我通过注解的方式定义了3个增强方法和一个切入点。因为切入点和目标方法匹配所以目标方法执行时,3个增强方法也有序执行了。这个过程Spring源码是如何实现的呢?
二、源码分析
源码分析前先列出需要分析的主要步骤
- 通过自动装配,注入一个后处理器bean(AnnotationAwareAspectJAutoProxyCreator)。
- 后处理器bean对符合要求的bean进行动态代理。
- 被代理的bean方法调用。
下面基于这个流程跟下源码
2.1 注入AnnotationAwareAspectJAutoProxyCreator
SpringBoot通过自动装配类AopAutoConfiguration完成AnnotationAwareAspectJAutoProxyCreator的注册。先看下AopAutoConfiguration
@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 {
//jdk分支
//会走这个分支 因为配置文件里我设置了proxy-target-class=false
@Configuration(proxyBeanMethods = false)
//重点看这个注解。与cglib分支的区别就是proxyTargetClass=false
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
static class JdkDynamicAutoProxyConfiguration {
}
//cglib分支
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
... 略
}
接着跟下@EnableAspectJAutoProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//跟这个注册器 既然是注册了一个bean,那肯定要跟注册器了
@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}.
*/
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;
}
接着跟@AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//继续跟这里 注册AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
//这个分支这次不跟进了
if (enableAspectJAutoProxy != null) {
//设置AnnotationAwareAspectJAutoProxyCreator中的proxyTargetClass
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
//强制使用cglib代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//设置代理对象是否可以暴漏
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
接着跟AopConfigUtils类,最终将AnnotationAwareAspectJAutoProxyCreator注册到工厂
public abstract class AopConfigUtils {
//入口方法
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
//继续跟这里
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}
//这里将AnnotationAwareAspectJAutoProxyCreator注册到工厂
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
}
可以看到AnnotationAwareAspectJAutoProxyCreator本质是一个BeanPostProcessor
2.2 后处理器Bean对符合要求的bean进行动态代理
处理方法使用了BeanPostProcessor的postProcessAfterInitialization方法。该方法由AnnotationAwareAspectJAutoProxyCreator的太爷爷AbstractAutoProxyCreator类实现。下面跟下这个方法
//入口方法 对bean执行初始化后处理
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//重点跟这里
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
// AOP实现的核心方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...略
// 构建Advisor集合
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;
}
这个方法主要包含两个部分。
- 获取与被处理bean匹配的Advisor集合
- 对Advisor集合非空的bean创建代理类
这里先回答两个问题
- 为什么说specificInterceptors是Advisor集合,本次只对@Aspect注解实现AOP的源码进行分析,在这种情况下getAdvicesAndAdvisorsForBean()方法返回的都是Advisor对象。
- 为什么对Advisor集合非空的bean创建代理对象呢?这里先简单介绍下Advisor对象。该对象包含一个增强方法(Advice)和一个PointCut(用于和目标bean的方法匹配)。也就是说如果Advisor集合非空就说明bean有方法需要被增强,所以这个bean需要被代理。
接下来基于这两部分继续分析
2.2.1 获取与被处理bean匹配的Advisor集合
跟进getAdvicesAndAdvisorsForBean方法,该方法由子类AbstractAdvisorAutoProxyCreator实现
//入口方法
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//跟这里
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
//核心方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取所有Advisor对象集合
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//获取与当前bean匹配的Advisor对象集合
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
到这里又出现了两个分支,首先获取所有Advisor对象集合,然后获取与当前bean匹配的Advisor对象集合。下面依次跟进
2.2.1.1 获取所有Advisor对象集合
跟进findCandidateAdvisors方法,该方法由AnnotationAwareAspectJAutoProxyCreator类实现
protected List<Advisor> findCandidateAdvisors() {
//原始构建Advisor的方式 这次不看这个分支了
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
//重点看这个分支 基于@Aspect注解构建Advisor对象
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
跟进buildAspectJAdvisors方法,该方法由BeanFactoryAspectJAdvisorsBuilder类实现。该方法主要作用是将所有被@Aspect注释的bean转化为一个Advisor对象集合。主要步骤如下
- 获取所有bean名称
- 挑选出被@Aspect注释的bean名称
- 基于bean名称构建元数据工厂(MetadataAwareAspectInstanceFactory),该工厂可以创建@Aspect注释的bean
- 最后使用全局变量advisorFactory,将MetadataAwareAspectInstanceFactory构建成一组Advisor对象
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
//首次构建Advisor
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//获取所有bean名称
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//获取被@Aspect注释的bean名称
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
//构建元数据工厂,该工厂可以获取被@Aspect注释的bean对象
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//核心方法:使用advisorFactory对象的getAdvisors方法构建Advisor
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
//进行缓存
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
//非首次基于缓存构建Advisor
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
继续跟进this.advisorFactory.getAdvisors()方法,目的是将MetadataAwareAspectInstanceFactory变成一组Advisor对象。其中全局变量this.advisorFactory是ReflectiveAspectJAdvisorFactory类型的。该全局变量在BeanFactoryAspectJAdvisorsBuilder的构造器中创建。这个工厂主要用来构建AOP所需要的核心对象Advisor、Pointcut、Advice。主要流程如下
- 获取@Aspect注释的bean的所有非@Pointcut注释的方法
- 如果方法被这5种(@Around,@Before.class,@After, @AfterReturning,@AfterThrowing)注解中的任意一个注释,为其创建Pointcut对象
- 如果Pointcut对象非空,构建Advisor对象。其构造函数中包含Pointcut对象,并且其构造函数中会创建Advice对象
接着跟下这个方法
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
//对元数据工厂进一步封装,目的是保证获取的bean是单例模式。这里不重点关注了
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//获取bean中所有非@Pointcut注释的方法
for (Method method : getAdvisorMethods(aspectClass)) {
//核心方法 构建Advisor对象 跟进这里
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 该分支 本次不关注
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 该分支 本次不关注
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
//创建Advisor对象
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
//为被(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class)注释的方法创建Pointcut对象
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
//创建Advisor对象 看看这个构造方法,将自己也传入的目的是为了后续构建Advice
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
跟InstantiationModelAwarePointcutAdvisorImpl构造方法
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
//构建AOP核心对象的工厂
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
//构建元数据bean的工厂
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
//懒加载分支 这次不重点关注了
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
//关注正常分支 跟这里
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
//Advice的创建 跟这里
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
//创建Adivce对象
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
//可以看到Advice也是由ReflectiveAspectJAdvisorFactory创建的
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
跟进ReflectiveAspectJAdvisorFactory的getAdvice方法
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
//5种Advice的创建。可以看出Advice封装了一个只差入参就能被调用的增强方法。通过反射调用一个方法需要3个基本元素,入参、方法对象、实体类。其构造方法中包含了方法对象和元素据工厂(可以随时创建实体类)。
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
2.2.1.2 获取与被处理bean匹配的Advisor对象集合
回到AbstractAdvisorAutoProxyCreator类的findEligibleAdvisors方法。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//candidateAdvisors对象已经初始化完毕。其内部的类型是InstantiationModelAwarePointcutAdvisorImpl
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//接着跟这个方法
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
//匹配方法
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//最终的匹配任务委托给了AopUtils类
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
现在所有被@Aspect注释的bean已经被转化成了InstantiationModelAwarePointcutAdvisorImpl对象,封装在candidateAdvisors中。InstantiationModelAwarePointcutAdvisorImpl本质上是PointcutAdvisor类型的而不是IntroductionAdvisor类型的,所以后续IntroductionAdvisor类型的处理不跟进了。该方法主要流程是便利所有Advisor,用Advisor的切入点表达式与被处理bean以及该bean的所有父辈的所有方法进行匹配,只要匹配一条就将Advisor加入目标集合。接着跟进AopUtils的findAdvisorsThatCanApply方法。
//入口方法
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
//IntroductionAdvisor相关的分支不关注了
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
//匹配成功放入结果集
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//跟进canApply方法1
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
//canApply方法1
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
//IntroductionAdvisor的分支 不关注了
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
//重点看这里
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
//跟进canApply方法2
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
//canApply方法2
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
//pc的类型是AspectJExpressionPointcut本质上是IntroductionAwareMethodMatcher
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//AspectJExpressionPointcut类型的pc,pc.getMethodMatcher会返回pc自己
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
//这里会执行强转
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
//将被处理的bean以及其所有父辈放入classes集合中
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
//依次便利bean以及其父辈
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
//便利每个类的所有方法
for (Method method : methods) {
//这里会走introductionAwareMethodMatcher.matche方法完成方法级别的匹配
//任何一个方法匹配 都返回true
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
2.2.2 创建代理对象
回到AbstractAutoProxyCreator的wrapIfNecessary方法。后续流程主要是将被处理bean的封装类和与被处理bean相关的Advior以及采用哪种方法代理(proxyTargetClass)统一委托给ProxyFactory完成代理对象的创建。
//入口方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//目前与被处理bean匹配的Advior对象已被封装到specificInterceptors对象中
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//将被处理bean的封装类和与被处理bean相关的Advior交给方法1进行代理对象的创建,跟进方法1
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;
}
//方法1
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//最终委托proxyFactory类完成后续处理
ProxyFactory proxyFactory = new ProxyFactory();
//这里将proxyTargetClass的值赋予了proxyFactory,用于确定使用jdk还是cglib
//proxyTargetClass的值最早来至@EnableAspectJAutoProxy(proxyTargetClass = false)注解
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//将specificInterceptors统一转化为Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//将advisors交给委托对象
proxyFactory.addAdvisors(advisors);
//将被处理bean的封装类交给委托对象
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//执行动态代理
return proxyFactory.getProxy(getProxyClassLoader());
}
继续跟进ProxyFactory的getProxy方法
public Object getProxy(@Nullable ClassLoader classLoader) {
//createAopProxy()不具体跟了,该方法主要做了两件事
//1--创建代理工厂(只有JdkDynamicAopProxy和ObjenesisCglibAopProxy两种),重点看JdkDynamicAopProxy
//2--将携带Advisor集合和被处理bean封装类的ProxyFactory传给JdkDynamicAopProxy的advised属性
return createAopProxy().getProxy(classLoader);
}
继续跟进JdkDynamicAopProxy的getProxy方法
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
//拿到被处理bean的所有接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//创建动态代理,最有一个参数是this。也就是说JdkDynamicAopProxy是一个InvocationHandler
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
2.4 代理对象方法调用
基于上边的分析,JdkDynamicAopProxy本质上是一个InvocationHandler。所以代理方法的执行就是他的invoke方法。该方法主要做两件事
- 使用advised构建出一个有序的方法链
- 委托ReflectiveMethodInvocation执行方法链
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
//基类Object的方法不做代理
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//提供在被代理类中获取代理类的一种方法,这里不重点说了
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 重点1 使用advised构建出一个有序的方法链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果方法链是空的直接执行目标方法
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
//执行目标方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//重点2 委托ReflectiveMethodInvocation执行方法链
retVal = invocation.proceed();
}
// 这个分支不重点看了
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
2.4.1 方法链的创建
跟进getInterceptorsAndDynamicInterceptionAdvice方法
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
//其中全局变量this.advisorChainFactory是DefaultAdvisorChainFactory类型
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
跟进DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法。该方法从与被代理bean相关的Advisor中挑出与当前方法相关的Advisor,然后将拿到Advisor中的Advice并将其转化成MethodInterceptor类型,最终构建出一个MethodInterceptor数组即我们的方法链。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
//封装最终的方法链
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
//跟这个分支 因为我们的advisor就是PointcutAdvisor类型的
if (advisor instanceof PointcutAdvisor) {
//获取切入点,从与当前类匹配的Advisor中找出与当前方法匹配的Advisor
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
//如果匹配将advisor转化为MethodInterceptor对象,便于后续方法链的执行
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
//这个分支不跟进了
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
//这个分支不跟进了
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
这里有个问题,为什么要将Advice转化成MethodInterceptor类型呢?目的是将5中Advice对象统一适配成一种类型,这样在后续方法链的执行中可以抽公共方法。
下边是五种Advice转化成MethodInterceptor的情况
- AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice本身就是MethodInterceptor。直接强转
- AspectJMethodBeforeAdvice不是MethodInterceptor类型,通过适配器适配成MethodBeforeAdviceInterceptor
- AspectJAfterReturningAdvice不是MethodInterceptor类型,通过适配器适配成AfterReturningAdviceInterceptor
2.4.2 方法链的执行
方法链的执行跟ReflectiveMethodInvocation的proceed方法。
public Object proceed() throws Throwable {
//全局变量this.interceptorsAndDynamicMethodMatchers就是方法链
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//如果方法链执行完毕 执行目标方法(我们写的业务方法)
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//这次不关注这个分支,目标方法是一个重载方法时会进入这个分支
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
//正常分支 执行MethodInterceptor的invoke方法。这里主要就是增强方法的执行
else {
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
在方法链的创建中分析出MethodInterceptor有5中类型(AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice、MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor)接下来依次看下其invoke方法
2.4.2.1 方法链的执行MethodBeforeAdviceInterceptor的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
//这里的advice就是AspectJMethodBeforeAdvice
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
这里可以看到先执行增强方法,然后继续执行方法链。这里保证了AspectJMethodBeforeAdvice增强方法的先执行。
跟进AspectJMethodBeforeAdvice的before方法。看看如何通过反射执行的增强方法
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
//该方法由其父类AbstractAspectJAdvice统一实现
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
跟进AbstractAspectJAdvice的invokeAdviceMethod方法
protected Object invokeAdviceMethod(
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
throws Throwable {
//跟进方法1
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
//方法1
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
//通过反射完成增强方法的调用
//aspectJAdviceMethod就是之前封装的增强方法对象
//this.aspectInstanceFactory内部封装了被@Aspect注释的bean,在这里创建了bean实例
//最后的参数时这次方法调用传的
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
2.4.2.2 方法链的执行AfterReturningAdviceInterceptor的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
//这里的this.advice就是AspectJAfterReturningAdvice对象
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
可以看到先执行方法链中的其他方法,最后执行增强方法。保证了增强方法的后执行
跟进this.advice.afterReturning方法,看看如何通过反射执行的增强方法
public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
//和AspectJMethodBeforeAdvice一样逻辑 不继续跟进了
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
}
}
2.4.2.3 方法链的执行AspectJAfterAdvice的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
//增强方法执行
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
将增强方法放到finally中保证最终执行
2.4.2.4 方法链的执行AspectJAfterThrowingAdvice的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
//增强方法
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
将增强方法放到catch语句块中,保证异常时执行
2.4.2.5 方法链的执行AspectJAroundAdvice的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
最特殊的Advice,其将方法链封装到了ProceedingJoinPoint对象中并传给了增强方法。增强方法中可以通过控制方法链的调用时机达到和其他四种的Advice任意一个一样的效果。甚至可以达到其他4种的任意组合效果。相当于自定义MethodInvocation的invoke方法了
总结
这里在总结下总体流程
- 创建代理对象
- 1 自动装配注入AnnotationAwareAspectJAutoProxyCreator后置处理器
- 2 后置处理器将所有@Aspect注释的bean转化为一个Advisor集合
- 3 为匹配了Advisor的被处理bean创建代理对象
- 执行代理对象方法
- 1 创建方法执行链,将与当前方法匹配的Advisor集合转化为MethodInterceptor集合
- 2 执行方法链,依次执行MethodInterceptor的invoke方法。其方法内部保证了不同Advice的执行顺序