注释:

在上一篇,咱们对IOC外围局部流程曾经剖析结束,置信小伙伴们有所播种,从这一篇开始,咱们将会踏上新的旅程,即Spring的另一外围:AOP!

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

  • 切面(Aspect):指关注点模块化,这个关注点可能会横切多个对象。事务管理是企业级Java利用中无关横切关注点的例子。在Spring AOP中,切面能够应用在一般类中以@Aspect注解来实现。
  • 连接点(Join point):在Spring AOP中,一个连接点总是代表一个办法的执行,其实就代表加强的办法。
  • 告诉(Advice):在切面的某个特定的连接点上执行的动作。告诉有多种类型,包含aroundbeforeafter等等。许多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@EnableAspectJAutoProxypublic 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@Componentpublic 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

@Overrideprotected boolean shouldSkip(Class<?> beanClass, String beanName) {  // 寻找advisor  List<Advisor> 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<Advisor> findCandidateAdvisors() {  // 寻找实现了Advisor接口的类, 因为咱们个别不会以接口的形式实现切面,这里返回null  List<Advisor> advisors = super.findCandidateAdvisors();  if (this.aspectJAdvisorsBuilder != null) {    // 这里将解析出所有的切面    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());  }  return advisors;}

buildAspectJAdvisors

public List<Advisor> buildAspectJAdvisors() {  // aspectBeanNames有值则阐明切面已解析结束  List<String> aspectNames = this.aspectBeanNames;  // Double Check  if (aspectNames == null) {    synchronized (this) {      aspectNames = this.aspectBeanNames;      if (aspectNames == null) {        List<Advisor> 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<Advisor> 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<Advisor> advisors = new ArrayList<>();  // 获取到所有解析好的advisor  for (String aspectName : aspectNames) {    List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);    if (cachedAdvisors != null) {      advisors.addAll(cachedAdvisors);    }        return advisors;    }

advisorFactory.getAdvisors

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {    // 获取到标识了@AspectJ的class,其实就是刚刚封装的class  Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();  // 获取className  String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();    List<Advisor> 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<Method> getAdvisorMethods(Class<?> aspectClass) {  final List<Method> 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.setExpression(aspectJAnnotation.getPointcutExpression());  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.SINGLETONAjTypeSystem.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.parsePointcutExpression(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<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);  return advisors.toArray();}

findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {  // 先获取到所有的advisor, 这里和解析过程雷同,因为曾经解析好,所以会间接从缓存中取出  List<Advisor> candidateAdvisors = findCandidateAdvisors();  // 筛选出匹配的advisor  List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);  // 减少一个默认的advisor  extendAdvisors(eligibleAdvisors);  if (!eligibleAdvisors.isEmpty()) {    // 排序    eligibleAdvisors = sortAdvisors(eligibleAdvisors);  }  return eligibleAdvisors;}

findAdvisorsThatCanApply

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

findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz){  List<Advisor> 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() {  obtainPointcutExpression();  return this;}

obtainPointcutExpression

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

buildPointcutExpression

private PointcutExpression buildPointcutExpression(@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.parsePointcutExpression(replaceBooleanOperators(resolveExpression()),                                        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 = obtainPointcutExpression();  // 应用切点表达式进行粗筛  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<Object> 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<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {  // 将所有advisor中的advice取出并封装成intercept  return this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);}
public List<Object> 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<MethodInterceptor> 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;  }}
所以如果咱们的业务办法产生了异样,会调用到异样告诉,而这里又把异样往外抛,所以afterReturn就会被跳过间接到after的finally办法

当初currentInterceptorIndex值为3了,再回调最后的办法中时,就会调用到咱们的业务办法了。调用结束则进行归的过程,调用过程便完结了。

以上,便是整个AOP的过程了

本篇文章中波及到图片的矢量图地址为:https://www.processon.com/vie...,有须要的小伙伴可自取

下文预报:Spring源码剖析之事务管理(上)

Spring 源码系列
  1. Spring源码剖析之 IOC 容器预启动流程(已完结)
  2. Spring源码剖析之BeanFactory体系结构(已完结)
  3. Spring源码剖析之BeanFactoryPostProcessor调用过程(已完结)
  4. Spring源码剖析之Bean的创立过程(已完结)
  5. Spring源码剖析之什么是循环依赖及解决方案(已完结)
  6. Spring源码剖析之AOP从解析到调用(已完结)
  7. Spring源码剖析之事务管理(上),事物治理是spring作为容器的一个特点,总结一下他的根本实现与原理吧
  8. Spring源码剖析之事务管理(下) ,对于他的底层事物隔离与事物流传原理,重点剖析一下
Spring Mvc 源码系列
  1. SpringMvc体系结构
  2. SpringMvc源码剖析之Handler解析过程
  3. SpringMvc源码剖析之申请链过程
另外笔者公众号:奇客工夫,有更多精彩的文章,有趣味的同学,能够关注