spring——AOP原理及源碼(一)

教程共分爲五篇,從AOP實例的構建及其重要組件、基本運行流程、容器建立流程、關鍵方法調用、原理總結概括等幾個方面一步步走進AOP的世界。html

本篇主要爲讀者演示構建AOP實例及AOP核心組件分析。java

 

1、項目構建

讀者可直接下載示例工程,或複製如下的代碼到本地工程開啓教程。mysql

<?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

項目目錄結構以下:git

到這裏,咱們的項目是構建完了。github

 

 

2、日誌切面方法測試

打開測試類,運行測試方法spring

 咱們能夠看到,總共打印了四行,除了第二行打印是業務方法的調用,其餘都是調用日誌切面類中的方法打印出來的。sql

這就是AOP的使用效果,除了用在日誌,還有其餘不少用法,這裏就不贅述了。apache

 

 

3、關鍵組件探究

爲何AOP能在業務方法調用的先後和發生異常時調用切面方法呢,首先咱們須要瞭解它引入了什麼組件。maven

爲了讓AOP起做用,咱們須要在配置類上添加@EnableAspectJAutoProxy註解,從字面上看,翻譯爲啓動切面自動代理,那它是怎麼啓動的呢ide

ctrl+鼠標左鍵進入這個註解,咱們能夠看到EnableAspectJAutoProxy接口使用@Import註解導入了AspectJAutoProxyRegistrar這個類

再次ctrl+鼠標左鍵進入AspectJAutoProxyRegistrar,能夠看到,它實現了ImportBeanDefinitionRegistrar接口。

此接口中的registerBeanDefinitions方法,正是用來像容器中註冊組件的。

看來想要知道@EnableAspectJAutoProxy註解到底給容器中添加了什麼組件,咱們須要進行調試,找到ImportBeanDefinitionRegistrar方法給容器中添加的組件。這個組件必定就是AOP實現的關鍵。

 

 

 4、調試尋找組件

以下圖,咱們在ImportBeanDefinitionRegistrar接口的註冊方法中打上斷點。

 

點擊debug開始調試,程序來到了AspectJAutoProxyRegistrar的registerBeanDefinitions方法

正在執行的是AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry),方法的字面意思:註冊切面自動代理創造組件若是須要的話

 

接着進入這個方法直到如下這個方法,能夠看到返回的是BeanDefinition類型,說明在方法裏面有組件定義或註冊相關的動做。

 110行進行判斷,若是容器中存在AUTO_PROXY_CREATOR_BEAN_NAME這個定義信息,進行如下判斷,巴拉巴拉,最後return null,退出這個方法。

若是不存在,能夠看到在125行已經有註冊名爲AUTO_PROXY_CREATOR_BEAN_NAME的組件的動做。

把鼠標放在AUTO_PROXY_CREATOR_BEAN_NAME上,能夠看到它實際是叫internalAutoProxyCreator

接着咱們進行下一步,到110行時,顯然第一次它是不存在這個類的,因此跳過if{}中的內容,到121行時,咱們能夠看看cls的信息,發現這個類叫AnnotationAwareAspectJAutoProxyCreator

 

 到125行時,已經設置好AnnotationAwareAspectJAutoProxyCreator的各類屬性,將其命名爲internalAutoProxyCreator註冊進容器,在126行進行返回。

在上面過程當中,咱們能夠獲得的結論是,@EnableAspectJAutoProxy註解實際上就是給容器中添加了名爲internalAutoProxyCreator的組件,實際就是AnnotationAwareAspectJAutoProxyCreator這個類。

咱們能夠得出AnnotationAwareAspectJAutoProxyCreator就是實現AOP的核心組件。

接下來咱們來探究一下AnnotationAwareAspectJAutoProxyCreator的繼承關係,以及它是什麼。

 

 

5、AnnotationAwareAspectJAutoProxyCreator組件是什麼

進入這個類,發現它繼承了AspectJAwareAdvisorAutoProxyCreator

 

那麼AspectJAwareAdvisorAutoProxyCreator又是什麼呢,接着進入AspectJAwareAdvisorAutoProxyCreator

發現AspectJAwareAdvisorAutoProxyCreator又繼承了AbstractAdvisorAutoProxyCreator

咱們接着進入AbstractAdvisorAutoProxyCreator中查看

能夠看到AbstractAdvisorAutoProxyCreator繼承了AbstractAutoProxyCreator

再進入AbstractAutoProxyCreator

能夠看到AbstractAutoProxyCreator繼承了ProxyProcessorSupport

並實現了SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware兩個接口

 

 接下來咱們主要看這兩個接口

SmartInstantiationAwareBeanPostProcessor明顯是一個後置處理器接口,BeanFactoryAware是一個底層組件接口,實現BeanFactoryAware就能夠注入並調用BeanFactory。

通過層層的進入,能夠獲得以下的關係

這樣看來,咱們能夠得出結論——AnnotationAwareAspectJAutoProxyCreator是一個後置處理器後置處理器原理

 

 

總結

  通過以上五個步驟,咱們看到AOP的使用效果,發現了AOP的核心組件AnnotationAwareAspectJAutoProxyCreator是一個後置處理器,理清了AnnotationAwareAspectJAutoProxyCreator的繼承實現關係。

總得來講,就是明白了核心組件是什麼。

 

在接下來的篇章咱們將從核心組件在哪發揮做用,什麼時候發揮,以及作了什麼,一步步深刻原理。

相關文章
相關標籤/搜索