千家信息网

Spring源码分析之如何AOP从解析到调用

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容主要讲解"Spring源码分析之如何AOP从解析到调用",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Spring源码分析之如何AOP从解析到调用"
千家信息网最后更新 2026年11月03日Spring源码分析之如何AOP从解析到调用

本篇内容主要讲解"Spring源码分析之如何AOP从解析到调用",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Spring源码分析之如何AOP从解析到调用"吧!

首先,为了让大家能更有效的理解AOP,先带大家过一下AOP中的术语:

  • 切面(Aspect):指关注点模块化,这个关注点可能会横切多个对象。事务管理是企业级Java应用中有关横切关注点的例子。在Spring AOP中,切面可以使用在普通类中以@Aspect注解来实现。
  • 连接点(Join point):在Spring AOP中,一个连接点总是代表一个方法的执行,其实就代表增强的方法。
  • 通知(Advice):在切面的某个特定的连接点上执行的动作。通知有多种类型,包括 around, before和 after等等。许多AOP框架,包括Spring在内,都是以拦截器做通知模型的,并维护着一个以连接点为中心的拦截器链。
  • 目标对象(Target):目标对象指将要被增强的对象。即包含主业务逻辑的类的对象。
  • 切点(Pointcut):匹配连接点的断言。通知和切点表达式相关联,并在满足这个切点的连接点上运行(例如,当执行某个特定名称的方法时)。切点表达式如何和连接点匹配是AOP的核心:Spring默认使用AspectJ切点语义。
  • 顾问(Advisor):顾问是Advice的一种包装体现,Advisor是Pointcut以及Advice的一个结合,用来管理Advice和Pointcut。
  • 织入(Weaving):将通知切入连接点的过程叫织入
  • 引入(Introductions):可以将其他接口和实现动态引入到targetClass中

一个栗子

术语看完了,我们先上个Demo回顾一下吧~

  1. 首先,使用EnableAspectJAutoProxy注解开启我们的AOP

    @ComponentScan(basePackages = {"com.my.spring.test.aop"})
    @Configuration
    @EnableAspectJAutoProxy
    public class Main {

    public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
    IService service = context.getBean("service", IService.class);
    service.doService();
    }
    }
  2. 写一个接口

    public interface IService {

    void doService();
    }
  3. 写一个实现类

    @Service("service")
    public class ServiceImpl implements IService{

    @Override
    public void doService() {
    System.out.println("do service ...");
    }
    }
  4. 写一个切面

    @Aspect
    @Component
    public class ServiceAspect {

    @Pointcut(value = "execution(* com.my.spring.test.aop.*.*(..))")
    public void pointCut() {
    }

    @Before(value = "pointCut()")
    public void methodBefore(JoinPoint joinPoint) {
    String methodName = joinPoint.getSignature().getName();
    System.out.println("执行目标方法 【" + methodName + "】 的【前置通知】,入参:" + Arrays.toString(joinPoint.getArgs()));
    }

    @After(value = "pointCut()")
    public void methodAfter(JoinPoint joinPoint) {
    String methodName = joinPoint.getSignature().getName();
    System.out.println("执行目标方法 【" + methodName + "】 的【后置通知】,入参:" + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(value = "pointCut()")
    public void methodReturn(JoinPoint joinPoint) {
    String methodName = joinPoint.getSignature().getName();
    System.out.println("执行目标方法 【" + methodName + "】 的【返回通知】,入参:" + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterThrowing(value = "pointCut()")
    public void methodThrow(JoinPoint joinPoint) {
    String methodName = joinPoint.getSignature().getName();
    System.out.println("执行目标方法 【" + methodName + "】 的【异常通知】,入参:" + Arrays.toString(joinPoint.getArgs()));
    }
    }
  5. 测试运行

    执行目标方法 【doService】 的【前置通知】,入参:[]
    do service ...
    执行目标方法 【doService】 的【返回通知】,入参:[]
    执行目标方法 【doService】 的【后置通知】,入参:[]

以上

Demo看完了,运行效果也出来了,AOP已生效,但如何生效的呢?相比于我们普通使用Bean的Demo,在这里,我们只不过加上了一个@EnableAspectJAutoProxy注解以及一个标识了@Aspectj的类,那么我们先看看@EnableAspectJAutoProxy这个注解做了什么吧~

开启AOP

以下是笔者所画的大致流程图

其中AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,所以在处理BeanFactoryPostProcessor逻辑时将会调用registerBeanDefinitions方法,此时就会把AnnotationAwareAspectJAutoProxyCreator注册到容器中,其中BeanFactoryPostProcessor的逻辑就不再说了,往期文章有过详细分析。而AnnotationAwareAspectJAutoProxyCreator的类图如下:

我们发现AnnotationAwareAspectJAutoProxyCreator是实现了BeanPostProcessor接口的类,所以它其实是一个后置处理器,那么,还记得在创建Bean过程中的BeanPostProcessor九次调用时机吗?不记得也没关系,AnnotationAwareAspectJAutoProxyCreator起作用的地方是在bean的实例化前以及初始化后,分别对应着解析切面和创建动态代理的过程,现在,就让我们先来看看解析切面的过程吧~

解析切面

解析切面的流程如下图所示:

我们已经了解到切面解析的过程是由AnnotationAwareAspectJAutoProxyCreator完成的,而AnnotationAwareAspectJAutoProxyCreator又继承了AbstractAutoProxyCreator,所以首先,我们先会来到AbstractAutoProxyCreator#postProcessBeforeInstantiation

public Object postProcessBeforeInstantiation(Class beanClass, String beanName) {
// class类型是否为(Advice, Pointcut, Advisor, AopInfrastructureBean)
// shouldSkip中将会解析切面
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}

调用到子类的AspectJAwareAdvisorAutoProxyCreator#shouldSkip

@Override
protected boolean shouldSkip(Class beanClass, String beanName) {
// 寻找advisor
List candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}

findCandidateAdvisors

protected List findCandidateAdvisors() {
// 寻找实现了Advisor接口的类, 由于我们一般不会以接口的方式实现切面,这里返回null
List advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
// 这里将解析出所有的切面
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}

buildAspectJAdvisors

public List buildAspectJAdvisors() {
// aspectBeanNames有值则说明切面已解析完毕
List aspectNames = this.aspectBeanNames;
// Double Check
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 取出是Object子类的bean,其实就是所有的bean
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
// 获得该bean的class
Class beanType = this.beanFactory.getType(beanName);
// 判断是否有标识@AspectJ注解
if (this.advisorFactory.isAspect(beanType)) {
// 将beanName放入集合中
aspectNames.add(beanName);
// 将beanType和beanName封装到AspectMetadata中
AspectMetadata amd = new AspectMetadata(beanType, beanName);
// Kind默认为SINGLETON
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 这里会通过@Before @After等标识的方法获取到所有的advisor
List classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 将获取到的所有advisor放入缓存
this.advisorsCache.put(beanName, classAdvisors);
}
advisors.addAll(classAdvisors);
}
}
}
// 将所有解析过的beanName赋值
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
// aspectNames不为空,意味有advisor,取出之前解析好的所有advisor
List advisors = new ArrayList<>();
// 获取到所有解析好的advisor
for (String aspectName : aspectNames) {
List cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
return advisors;
}

advisorFactory.getAdvisors

public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取到标识了@AspectJ的class,其实就是刚刚封装的class
Class aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 获取className
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();

List advisors = new ArrayList<>();

// 拿出该类除了标识@PointCut的所有方法进行遍历 getAdvisorMethods时会对method进行一次排序
// 排序顺序 Around, Before, After, AfterReturning, AfterThrowing
for (Method method : getAdvisorMethods(aspectClass)) {
// 获取到advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
// 加入到集合中
advisors.add(advisor);
}
}
}

我们先看下getAdvisorMethods方法

private List getAdvisorMethods(Class aspectClass) {
final List methods = new ArrayList<>();
// 循环遍历该类和父类的所有方法
ReflectionUtils.doWithMethods(aspectClass, method -> {
// 排除@PointCut标识的方法
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
if (methods.size() > 1) {
// 以Around, Before, After, AfterReturning, AfterThrowing的顺序自定义排序
methods.sort(METHOD_COMPARATOR);
}
return methods;
}

不知道小伙伴们对ReflectionUtils.doWithMethods这个工具类熟不熟悉呢,这个工具类在之前分析Bean创建过程时可是出现了好多次呢,并且我们也是可以使用的

现在,已经获取到切面中的所有方法了,那么接下来就该对这些方法解析并进行封装成advisor了~

getAdvisor

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 获取方法上的切点表达式
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 封装成对象返回,创建对象时将会解析方法创建advice
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

获取切点表达式的过程其实非常简单,即是解析方法上的注解,取出注解上的value即可

getPointcut

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class candidateAspectClass) {
// 查找方法上和AspectJ相关注解
AspectJAnnotation aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
// 设置切点表达式
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
// PointcutExpression 为注解上value属性的值
ajexp.set_Expression(aspectJAnnotation.getPointcut_Expression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}

new InstantiationModelAwarePointcutAdvisorImpl,在这里,才会真正创建出advice

public InstantiationModelAwarePointcutAdvisorImpl(){
//...省略赋值过程...
// 实例化出advice
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
// 获取advice,aspectJAdviceMethod为方法,aspectName为切面类
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
public Advice getAdvice(){
// 根据方法获取到注解信息
AspectJAnnotation aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
AbstractAspectJAdvice springAdvice;
// 根据注解类型返回对象,创建对象的过程都是一样的,都是调用父类的构造方法
// candidateAdviceMethod为切面的方法,expressionPointcut是切点
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut
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;
//...省略其他的advice
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
return springAdvice;
}

springAdvice已创建完毕,意味着切面中的某个方法已经解析完毕了,其他的方法解析过程大致也是相似的

小结

其实解析切面本身并不复杂,只是Spring中将切面类封装来封装去容易使人混乱,如buildAspectJAdvisors方法中,封装了一个AspectMetadata amd = new AspectMetadata(beanType, beanName);,又立即发起判定amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON,其实这里完全可以变为AjTypeSystem.getAjType(currClass).getPerClause().getKind() == PerClauseKind.SINGLETON,AjTypeSystem.getAjType(currClass)为new AspectMetadata的一部分逻辑,笔者这里给大家总结一下吧。

首先,循环所有的beanName,找到带有@Aspectj注解的class, 获取到class中的所有方法进行遍历解析,取出方法注解上的值(切点:pointcut),然后把方法,切点表达式,封装了BeanFactory,BeanName的factory封装成相应的SpringAdvice, 由SpringAdvice和pointcut组合成一个advisor。

创建代理对象

切面已经解析完毕,接下来,我们就来看看如何把解析出的切面织入到目标方法中吧

但,在这之前,还有必要给小伙伴们补充一点前置知识。

我们知道,一个bean是否能够被aop代理,取决于它是否满足代理条件,即为是否能够被切点表达式所命中,而在Spring AOP中,bean与切点表达式进行匹配的是AspectJ实现的,并非Spring所完成的,所以我们先来看看AspectJ如何匹配出合适的bean的吧

栗子

首先需要引入org.aspectj:aspectjweaver依赖

一个Service,包名为com.my.spring.test.aop

package com.my.spring.test.aop;

/**
* 切点表达式可以匹配的类
*
*/
public class ServiceImpl{
/**
* 切点表达式可以匹配的方法
*/
public void doService() {
System.out.println("do service ...");
}
public void matchMethod() {
System.out.println("ServiceImpl.notMatchMethod");
}
}

然后,我们自己封装一个用于匹配的工具类,具体功能大家看注释哈哈

package com.my.spring.test.aspectj;

import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.ShadowMatch;

import java.lang.reflect.Method;

/**
* aop工具
*/
public class AOPUtils {
// AspectJ的固定写法,获取一个切点解析器
static PointcutParser parser = PointcutParser
.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
PointcutParser.getAllSupportedPointcutPrimitives(), ClassLoader.getSystemClassLoader());
// 切点表达式
private static PointcutExpression pointcutExpression;

/**
* 初始化工具类,我们需要先获取一个切点表达式
*
* @param expression 表达式
*/
public static void init(String expression){
// 解析出一个切点表达式
pointcutExpression = parser.parsePointcut_Expression(expression);
}

/**
* 第一次筛选,根据类筛选,也叫做粗筛
*
* @param targetClass 目标类
* @return 是否匹配
*/
public static boolean firstMatch(Class targetClass){
// 根据类筛选
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
}

/**
* 第二次筛选,根据方法筛选,也叫做精筛,精筛通过则说明完全匹配
* ps: 也可以使用该方法进行精筛,粗筛的目的是提高性能,第一次直接过滤掉不合适的类再慢慢精筛
*
* @param method 方法
* @return 是否匹配
*/
public static boolean lastMatch(Method method){
// 根据方法筛选
ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
return shadowMatch.alwaysMatches();
}

}

测试

public class AOPUtilsTest {

public static void main(String[] args) throws NoSuchMethodException {
// 定义表达式
String expression = "execution(* com.my.spring.test.aop.*.*(..))";
// 初始化工具类
AOPUtils.init(expression);
// 粗筛
boolean firstMatch = AOPUtils.firstMatch(ServiceImpl.class);
if(firstMatch){
System.out.println("第一次筛选通过");
// 正常情况应该是获取所有方法进行遍历,我这里偷懒了~
Method doService = ServiceImpl.class.getDeclaredMethod("doService");
// 精筛
boolean lastMatch = AOPUtils.lastMatch(doService);
if(lastMatch){
System.out.println("第二次筛选通过");
}
else{
System.out.println("第二次筛选未通过");
}
}
else {
System.out.println("第一次筛选未通过");
}
}
}

结果(就不截图了,怀疑的小伙伴可以自己试试~)

第一次筛选通过
第二次筛选通过

当我们新建一个类Test,把切点表达式换成

execution(* com.my.spring.test.aop.Test.*(..))

测试结果为

第一次筛选未通过

再把切点表达式换成指定的方法

execution(* com.my.spring.test.aop.*.matchMethod(..))

结果

第一次筛选通过
第二次筛选未通过

到这里,小伙伴们应该明白了AspectJ的使用方法吧

代理对象创建过程

接下来,我们就来看看Spring是如何使用AspectJ匹配出相应的advisor并创建代理对象的吧,以下为创建代理对象的大致路程图

创建代理对象是在bean初始化后完成的,所以对应的beanPostProcessor调用时机为postProcessAfterInitialization

AbstractAutoProxyCreator#postProcessAfterInitialization

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 获取缓存key值,其实就是beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 判断缓存中是否有该对象,有则说明该对象已被动态代理,跳过
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 根据bean获取到匹配的advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
return proxy;
}
return bean;
}

getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(
Class beanClass, String beanName, @Nullable TargetSource targetSource) {
// 获取合适的advisor
List advisors = findEligibleAdvisors(beanClass, beanName);
return advisors.toArray();
}

findEligibleAdvisors

protected List findEligibleAdvisors(Class beanClass, String beanName) {
// 先获取到所有的advisor, 这里和解析过程相同,由于已经解析好,所以会直接从缓存中取出
List candidateAdvisors = findCandidateAdvisors();
// 筛选出匹配的advisor
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 增加一个默认的advisor
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

findAdvisorsThatCanApply

protected List findAdvisorsThatCanApply(
List candidateAdvisors, Class beanClass, String beanName) {
// 查找匹配的advisor
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}

findAdvisorsThatCanApply

public static List findAdvisorsThatCanApply(List candidateAdvisors, Class clazz){
List eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// 判断是否匹配
if (canApply(candidate, clazz, hasIntroductions)) {
// 加入到合适的advisors集合中
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}

canApply

public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
// 判断是否匹配
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}

canApply

public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {
// 第一次筛选,对class筛选判断是否满足匹配条件
// 这里将会初始化切点表达式
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}

IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}

for (Class clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
// 循环所有方法进行第二次筛选,判断是否有方法满足匹配条件
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}

pc.getClassFilter()

public ClassFilter getClassFilter() {
obtainPointcut_Expression();
return this;
}

obtainPointcutExpression

private PointcutExpression obtainPointcut_Expression() {
if (this.pointcutExpression == null) {
// 确认类加载器
this.pointcutClassLoader = determinePointcutClassLoader();
// 创建切点表达式
this.pointcutExpression = buildPointcut_Expression(this.pointcutClassLoader);
}
return this.pointcutExpression;
}

buildPointcutExpression

private PointcutExpression buildPointcut_Expression(@Nullable ClassLoader classLoader) {
// 初始化切点解析器
PointcutParser parser = initializePointcutParser(classLoader);
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
for (int i = 0; i < pointcutParameters.length; i++) {
pointcutParameters[i] = parser.createPointcutParameter(
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
}
// 使用切点解析器进行解析表达式获取切点表达式
return parser.parsePointcut_Expression(replaceBooleanOperators(resolve_Expression()),
this.pointcutDeclarationScope, pointcutParameters);
}

initializePointcutParser

private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
// 获得切点解析器
PointcutParser parser = PointcutParser
.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
SUPPORTED_PRIMITIVES, classLoader);
parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
return parser;
}

pc.getClassFilter便是完成了以上事情,此时再进行调用matchs方法

public boolean matches(Class targetClass) {
PointcutExpression pointcutExpression = obtainPointcut_Expression();
// 使用切点表达式进行粗筛
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
}

introductionAwareMethodMatcher.matches 同样如此

以上便是寻找合适的advisor的过程,下面,就是通过这些advisor进行创建动态代理了

createProxy

protected Object createProxy(Class beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 将specificInterceptors(现在是Object)转化为Advisor返回
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 赋值到proxyFactory的advisors属性中
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
// 创建动态代理
return proxyFactory.getProxy(getProxyClassLoader());
}

proxyFactory.getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
// 创建代理对象
return createAopProxy().getProxy(classLoader);
}

createAopProxy

protected final synchronized AopProxy createAopProxy() {
// 创建AOP代理对象
return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// @EnableAspectJAutoProxy的proxyTargetClass是否配置为true
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如何是接口则创建jdk动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// cglib动态代理
return new ObjenesisCglibAopProxy(config);
}
// 默认是jdk动态代理
else {
return new JdkDynamicAopProxy(config);
}
}
public Object getProxy(@Nullable ClassLoader classLoader) {
// 获取到代理的接口
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 创建jdk代理,传入的为JdkDynamicAopProxy对象,里面包含了被代理的bean以及匹配的advisor
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

动态代理创建完成~

代理对象调用过程

对象都给你创建好了,接下当然是开..发起调用咯

以下是调用的大致流程图

代理对象被调用的是invoke方法,我们所创建的代理对象为JdkDynamicAopProxy,所以

JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
// 取出包装了被代理bean的对象->创建代理对象时的SingletonTargetSource, advised为ProxyFactory
TargetSource targetSource = this.advised.targetSource;
Object target = null;
// 拿到bean
target = targetSource.getTarget();
Class targetClass = (target != null ? target.getClass() : null);
// 将所有advisor中的advice取出,并转化为对应的interceptor
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 创建一个最外层的MethodInvocation用于发起调用
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 发起链式调用
Object retVal = invocation.proceed();
return retVal;
}

我们先看获取interceptor的过程

getInterceptorsAndDynamicInterceptionAdvice

public List getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class targetClass) {
// 将所有advisor中的advice取出并封装成intercept
return this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
}
public List getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class targetClass) {
// 创建一个advisor适配器的注册器用于转化advice,创建时将默认注册三个适配器
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
// 循环遍历所有advisor
for (Advisor advisor : advisors) {
// 将advisor中的advice转化为interceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
return interceptorList;
}
}

GlobalAdvisorAdapterRegistry.getInstance() 类初始化时调用静态方法

private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry()
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
public DefaultAdvisorAdapterRegistry() {
// 注册三个适配器
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
// 将适配器加入集合
this.adapters.add(adapter);
}

registry.getInterceptors 这里面包含了advice转化成interceptor的过程

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
// advice本身是否就是MethodInterceptor
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// 判断advice是哪个advice 如:(advice instanceof MethodBeforeAdvice)
if (adapter.supportsAdvice(advice)) {
// 将advice封装到对应的interceptor
interceptors.add(adapter.getInterceptor(advisor));
}
}
return interceptors.toArray(new MethodInterceptor[0]);
}

若adapter为MethodBeforeAdviceAdapter,则

public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}

其他advice转化过程相同

以上,便将所有的advice转化成了interceptor,接下来,则是经典的链式递归调用过程

以下过程小伙伴们可以对照流程图阅读,毕竟递归还是有些复杂,需要一定的功底

ReflectiveMethodInvocation#proceed

public Object proceed() throws Throwable {
// currentInterceptorIndex 初始值为-1
// 当currentInterceptorIndex等于advice的数量减一时,则调用目标方法
// 由于advice已排好序,所以调用顺序为before, after, afterReturn, afterThrowing
// 注意,并非调用到相应的advice就会执行advice方法,这里是类似递归调用的方式,会存在一个归过程
// 有些是递的时候发起调用,如beforeAdvice, 但有些则是归的时候发起调用,如afterAdvice
// 递归的终止条件则是这下面这个return invokeJoinpoint();
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// currentInterceptorIndex自增并获取到interceptor
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 将interceptro强转为MethodInterceptor发起调用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}

此时currentInterceptorIndex值为0,而我们的advice为4个(去除了默认的),所以当currentInterceptorIndex为3时便会调用我们的实际方法

首先调用的是MethodBeforeAdviceInterceptor

public Object invoke(MethodInvocation mi) throws Throwable {
// 调用前置通知
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}

mi为传入的this,所有mi.proceed()将会回到最开始的方法

再次循环,此时currentInterceptorIndex值为1

调用的是AspectJAfterAdvice

public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
// finally意味着不管怎样都会被调用
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}

继续,此时currentInterceptorIndex值为2

调用的是AfterReturningAdviceInterceptor

public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}

继续,此时currentInterceptorIndex值为3

调用的是AspectJAfterThrowingAdvice

public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
// 调用异常通知
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
// 往外抛出异常
throw ex;
}
}

到此,相信大家对"Spring源码分析之如何AOP从解析到调用"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

方法 切点 对象 代理 表达式 过程 切面 注解 目标 封装 动态 第一次 连接点 接口 工具 标识 分析 合适 小伙 小伙伴 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 山东特亿宝互联网科技有限公司 互联网科技工作委员会 北京路客互联网科技有限公司 科技互联网技术 互联网公司 科技公司 菲比寻常互联网科技 长亮科技 互联网金融 互联网科技汛 太原新华互联网科技学校怎么样 宁波青枫互联网科技有限公司 成都铂石互联网科技做什么的 畅思互联网科技 互联网科技如何创业 2021互联网科技公司排名 广州百诚互联网科技有限公司官网 浙南科技城互联网大厦招聘 互联网安防科技感 昆明中奇联合互联网科技 盐城市攀科互联网科技有限公司 亚光科技低轨卫星互联网 中国互联网科技发展 时间互联网络科技 菲比寻常互联网科技 互联网 视角下的科技创新 恒生科技互联网指数分析 科技与互联网的利与弊 欧洲十大科技互联网公司 互联网媒体平台算高科技产业 银川新华互联网科技学校联系电话 武汉亿视互联网科技有限公司
0