Spring——AOP原理及源码一【系列完】

系列介绍html

共分为五篇,按照AOP的运行流程演示并分析springAOP源码,总结流程java

系列流程mysql

从AOP实例的构建到重要组件分析、基本运行流程、关键方法调用、原理总结等几个方面一步步分解AOP源码git

本篇概述github

为读者演示构建AOP实例及AOP核心组件分析spring


 

 

1、项目构建

读者可直接下载示例工程,或复制如下的代码到本地工程开启教程。sql

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tlj</groupId>
    <artifactId>spring-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
    </dependencies>


</project>
pom.xml
package config; import aop.LogAspects; import aop.MathCalculator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @EnableAspectJAutoProxy @Configuration public class ConfigOfAOP { @Bean public MathCalculator calculator(){ return new MathCalculator(); } @Bean public LogAspects logAspects(){ return new LogAspects(); } }
ConfigOfAOP
package aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import java.util.Arrays; /** * 切面类 */ @Aspect public class LogAspects { @Pointcut("execution(public int aop.MathCalculator.*(..))") public void poinCut(){} @Before("poinCut()") public void logStart(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); System.out.println(joinPoint.getSignature().getName()+" 运行。。。@Before "+ Arrays.asList(args)); } @After("poinCut()") public void logEnd(){ System.out.println("除法结束..@After"); } @AfterReturning(value = "poinCut()",returning = "result")//获取方法返回值
    public void logReturning(Object result){ System.out.println("除法正常返回..@AfterReturning "+result); } @AfterThrowing(value = "poinCut()",throwing = "e") public void logException(Exception e){ System.out.println("除法异常..@AfterThrowing "+e); } }
LogAspects
package aop; public class MathCalculator { public int div(int i,int j){ System.out.println("MathCalculator"); return i/j; } }
MathCalculator

项目目录结构以下:apache

到这里,构建了一个简单的切面功能demomaven


 

 

 

2、运行测试

打开测试类,运行测试方法ide


 

最终效果

总共打印了四行,第二行是业务方法的调用,其余都是调用日志切面类中的方法打印的。

这就是AOP的使用效果,除了用在日志,还有其余不少用法,这里就不赘述了。

 

 

3、关键组件探究

为何AOP能在业务方法调用的先后和发生异常时调用切面方法呢,首先咱们须要了解它引入了什么组件。

为了让AOP起做用,咱们须要在配置类上添加@EnableAspectJAutoProxy注解,从字面上看,翻译为启动切面自动代理,那它是怎么启动的呢

ctrl+鼠标左键进入这个注解,咱们能够看到EnableAspectJAutoProxy接口使用@Import注解导入了AspectJAutoProxyRegistrar这个类


 

再次ctrl+鼠标左键进入AspectJAutoProxyRegistrar,能够看到,它实现了ImportBeanDefinitionRegistrar接口。

此接口中的registerBeanDefinitions方法,正是用来向容器中注册组件的。

接下来来看@EnableAspectJAutoProxy注解到底给容器中注册了什么组件。这是AOP实现的关键。

 

 

4、调试寻找组件

以下图,咱们在ImportBeanDefinitionRegistrar接口的注册方法中打上断点。


 

点击debug开始调试,程序来到了AspectJAutoProxyRegistrar的registerBeanDefinitions方法

正在执行的是AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)

(字面意思为:注册切面自动代理创造组件若是须要的话)


 

接着进入这个方法直到如下这个方法,能够看到返回的是BeanDefinition类型,而BeanDefinition是用来保存bean定义信息的

上图所示,一进来先进行判断,若是容器中存在AUTO_PROXY_CREATOR_BEAN_NAME定义信息,进行一些操做,最后return null。

若是不存在,能够看到在125行已经有注册名为AUTO_PROXY_CREATOR_BEAN_NAME的组件的动做,要将定义信息注册到容器中。

把鼠标放在AUTO_PROXY_CREATOR_BEAN_NAME上,能够看到它名为internalAutoProxyCreator

 

接着咱们进行下一步,到110行时,显然第一次容器中不存在这个类,因此跳过if{}中的内容

到121行时,经过bean的各类定义信息,new一个定义bean,用来保存这个bean的各类定义信息

经过cls的信息,发现注册的internalAutoProxyCreator实际为AnnotationAwareAspectJAutoProxyCreator

 

到125行时,已经设置好AnnotationAwareAspectJAutoProxyCreator的各类属性

并将其命名为internalAutoProxyCreator注册进容器,在126行进行返回。

注意:这里注册的是BeanDefinition,也就是bean的定义信息,并无建立bean实例

总结

到此为止@EnableAspectJAutoProxy给容器中添加了internalAutoProxyCreator的BeanDefinition组件

internalAutoProxyCreator中实际又是AnnotationAwareAspectJAutoProxyCreator这个类

因此咱们能够得出AnnotationAwareAspectJAutoProxyCreator就是实现AOP的核心组件

接下来咱们来看AnnotationAwareAspectJAutoProxyCreator的继承关系,看它究竟是什么

 

 

5、AnnotationAwareAspectJAutoProxyCreator组件是什么

进入这个类,发现它继承了AspectJAwareAdvisorAutoProxyCreator

 

那么AspectJAwareAdvisorAutoProxyCreator又是什么呢,接着进入AspectJAwareAdvisorAutoProxyCreator

发现AspectJAwareAdvisorAutoProxyCreator又继承了AbstractAdvisorAutoProxyCreator

咱们接着进入AbstractAdvisorAutoProxyCreator中查看

能够看到AbstractAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator

再进入AbstractAutoProxyCreator

能够看到AbstractAutoProxyCreator继承了ProxyProcessorSupport

并实现了SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware两个接口

因为接下来继承的ProxyProcessorSupport是一个基础工具类,就不往下分析了


 

接下来咱们主要看这两个接口

SmartInstantiationAwareBeanPostProcessor:从名字中带有PostProcessor看出是一个后置处理器接口

BeanFactoryAware:底层组件接口,和其余XXXAware同样,实现XXXAware接口就能够调用XXX组件

通过层层的进入,能够获得以下的关系:

 

从图得出结论——AnnotationAwareAspectJAutoProxyCreator是一个后置处理器后置处理器原理

 

 

总结

  通过以上五个步骤,咱们了解了AOP的使用效果

  找到了AOP的核心组件AnnotationAwareAspectJAutoProxyCreator

  理清了AnnotationAwareAspectJAutoProxyCreator的继承实现关系

  发现了AOP的核心组件本质上是一个后置处理器

 

下篇预知:在下一篇中咱们将从核心组件在哪发挥做用,什么时候发挥,以及作了什么,一步步深刻原理。

原文出处:https://www.cnblogs.com/Unicron/p/12386776.html

相关文章
相关标签/搜索