zoukankan      html  css  js  c++  java
  • Spring源码解析(三)--AOP实现原理

    一、前言

      本篇主要解析AOP的实现原理。如果需要查看如何使用,移步Spring注解驱动开发(三)--AOP使用

    二、原理简介

      AOP的实现原理主要分三部分:

      1.@EnableAspectJAutoProxy注解注入AOP的组件

      2.目标Bean创建时,封装成动态代理类

      3.目标方法调用时,调用代理方法

    三、具体实现

      @EnableAspectJAutoProxy注解,会引入AspectJAutoProxyRegistrar类,该类是实现接口ImportBeanDefinitionRegistrar,在容器启动时会调用registerBeanDefinitions()。该接口主要用于动态向Spring容器中注册组件。

      调用AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry),最终会向容器中注入AnnotationAwareAspectJAutoProxyCreator类。

        

      现在我们来研究AnnotationAwareAspectJAutoProxyCreator这个类,下图是该类的继承关系:

      这里我们主要关心的是接口InstantiationAwareBeanPostProcessor。该接口代表是Bean的后置处理器,主要是在Bean实例创建前后进行调用。而AOP正是利用这个时机,在Bean创建后判断是否该Bean需要被增强,如果需要则生成代理类。

      生成代理类的实现在postProcessAfterInstantiation()方法中,该方法的实现在AbstractAutoProxyCreator类中。调用wrapIfNecessary()生成代理类,如果需要的话。

      getAdvicesAndAdvisorsForBean()方法获取当前Bean的所有advice(增强点)。如果有的话,说明当前Bean需要生成代理类。getAdvicesAndAdvisorsForBean()的实现在AbstractAdvisorAutoProxyCreator类中。

        

      findCandidateAdvisors()的实现在AnnotationAwareAspectJAutoProxyCreator类中,通过调用this.aspectJAdvisorsBuilder.buildAspectJAdvisors()获取增强点。该方法中,会获取Spring容器中所有的Bean,然后遍历判断是否是切面类(@Aspect注解的类)。如果是切面类,通过增强器工厂(AspectJAdvisorFactory)将切面下的方法封装成Advisor对象并返回,如下图:

      获取所有增强点后,通过调用AopUtils工具类findAdvisorsThatCanApply方法判断是否是当前Bean的增强点。判断方式是根据类和切面的切点表达式进匹配。

        

      若当前类拥有增强点,则生成代理类。默认使用CGLIB动态代理创建,如果@EnableAspectJAutoProxy注解的proxyTargetClass属性配置为true,则使用JDK的动态代理创建。

      若使用CGLIB动态代理,当方法调用时,真正调用的是DynamicAdvisedInterceptor类的intercept方法。在该方法中,会根据当前Bean的增强点,生成一个拦截器链。如下图中,有一个默认的拦截器和五个增强点的拦截器。每个拦截器都实现MethodInterceptor接口。

      

      @Before 对应 MethodBeforeAdviceInterceptor

      @After 对应 AspectJAfterAdvice

      @AfterReturning 对应 AfterReturningAdviceInterceptor

      @AfterThrowing 对应 AspectJAfterThrowingAdvice

      @Around 对应 AspectJAroundAdvice

      控制切面方法执行的时机就是在拦截器中增强点和方法调用的顺序不同导致的,如下图:

        

    《Spring源码解析(一)--Spring容器刷新》

    《Spring源码解析(二)--Spring Bean创建》

    《Spring源码解析(三)--AOP实现原理》

  • 相关阅读:
    过滤器
    联系数据库 电话本例子
    连接数据库日志例题
    登录注册 servlet
    Pandas截取列部分字符,并据此修改另一列的数据
    Excel 如何判断某列哪些单元格包含某些字符
    Pandas逐行读取Dateframe并转为list
    Pandas: 使用str.replace() 进行文本清洗
    如何在xlwt中编写多个列的单元格?
    python:循环定义、赋值多个变量
  • 原文地址:https://www.cnblogs.com/zhuqianchang/p/11423611.html
Copyright © 2011-2022 走看看