AspectJ安裝AspectJ下載AspectJ環境變量配置IDEA下配置AspectJ激活AspectJ支持插件添加aspectjrt.jar依賴或Maven依賴使用AspectJ編譯器(ajc)AspectJ簡單示例示例一示例二問題記錄參考文獻php
AspectJ 是一個基於 Java 語言的 AOP 框架,提供了強大的 AOP 功能,其餘不少 AOP 框架都借鑑或採納其中的一些思想。css
AspectJ 是 Java 語言的一個 AOP 實現,其主要包括兩個部分:第一個部分定義瞭如何表達、定義 AOP 編程中的語法規範,經過這套語言規範,咱們能夠方便地用 AOP 來解決 Java 語言中存在的交叉關注點問題;另外一個部分是工具部分,包括編譯器、調試工具等。html
AspectJ 是最先、功能比較強大的 AOP 實現之一,對整套 AOP 機制都有較好的實現,不少其餘語言的 AOP 實現,也借鑑或採納了 AspectJ 中不少設計。在 Java 領域,AspectJ 中的不少語法結構基本上已成爲 AOP 領域的標準。java
安裝 AspectJ 首先要到 AspectJ官網下載一個可執行的Jar包。web
便可下載到一個可執行的 JAR 包,我下的是 aspectj-1.8.14.jar,使用 java -jar aspectj-1.8.14.jar
命令, spring
屢次單擊「Next」按鈕, 並選擇合適的安裝目錄,便可成功安裝 AspectJ。 apache
在安裝了 AspectJ 以後,在其安裝目錄下,能夠看到以下的文件結構: 編程
├─bin // 該路徑下存放了 aj、aj五、ajc、ajdoc、ajbrowser 等命令。
│ ├─aj.bat
│ ├─aj5.bat
│ ├─ajbrowser
│ ├─ajbrowser.bat
│ ├─ajc // 其中 ajc 命令最經常使用,它的做用相似於 javac,用於對普通 Java 類進行編譯時加強。
│ ├─ajc.bat
│ ├─ajdoc
│ ├─ajdoc.bat
├─doc // 該路徑下存放了AspectJ的使用說明、參考手冊、API文檔等文檔。
├─lib // 該路徑下的4個Jar文件是AspectJ的核心類庫
│ ├─aspectjrt.jar
│ ├─aspectjtools.jar
│ ├─aspectjweaver.jar
│ ├─org.aspectj.matcher.jar
├─LICENSE-AspectJ.html 相關受權文件
└─README-AspectJ.html
複製代碼
CLASSPATH:.;D:\Java_About\Java_component\aspectj-1.8.14\lib\aspectjrt.jar;
Path:D:\Java_About\Java_component\aspectj-1.8.14\bin
複製代碼
測試是否安裝成功用 ajc 命令:微信
雖然 AspectJ 是 Eclipse 基金組織的開源項目,並且提供了 Eclipse 的 AJDT 插件(AspectJ Development Tools)來開發 AspectJ 應用,但 AspectJ 並非只能在 Eclipse 中開發。因爲我使用的是 IntelliJ IDEA 2019.1.2 版本,因此這裏介紹IDEA中如何開發 AspectJ。app
只有專業版(Ultimate)的 IntelliJ IDEA 才支持 AspectJ 的開發,並且 IDEA 也提供了 官方文檔。
在專業版 IDEA 中開發 AspectJ,須要確保下述插件被激活:
因爲本人使用的是 IDEA 2019.1.3 版本,因此同網上的說法不太同樣,配置以下:
這兩個插件在 2019 版本已經存在,所以不須要另外搜索進行安裝。
添加aspectjrt.jar依賴
在項目中添加 aspectjrt.jar
依賴,aspectjrt.jar
即 AspectJ 安裝目錄中lib
目錄下的 jar 包。
接着進行以下操做,將該 Jar 包添加進項目依賴中:
Project Structure
對話框(Ctrl+Shift+Alt+S)。添加Maven依賴
若是採用 Maven 來管理項目,則能夠在 pom.xml 文件中添加相關依賴。
<?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.msdn</groupId>
<artifactId>spring_aop</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.14</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.8.14</version>
</dependency>
</dependencies>
</project>
複製代碼
上述兩種方法均可以達到一樣的效果。
IDEA 默認使用javac
編譯器,若是要使用 AspectJ 的編譯器ajc
,須要在 IDEA 中進行相應的配置。
打開settings
對話框,而後作以下配置:
實際上,AspectJ 的用法很是簡單,就像咱們使用 JDK 編譯、運行 Java 程序同樣。下面經過一個簡單的程序來示範 AspectJ 的用法,並分析 AspectJ 如何在編譯時進行加強。
HelloWorld.java
public class HelloWorld {
public void sayHello(){
System.out.println("Hello AspectJ");
}
public static void main(String[] args) {
HelloWorld hello = new HelloWorld();
hello.sayHello();
}
}
複製代碼
該類中有一個 sayHello()
方法,該方法打印出了一句話!
假設如今咱們須要在 sayHello()
方法以前啓動事務,當該方法結束時關閉事務,那麼在傳統的編程模式下,咱們必須手動修改 sayHello()
方法。而若是使用 AspectJ,咱們則不須要修改上面的方法,只須要添加一個切面便可。
TxAspect.aj
public aspect TxAspect {
void around():call(void HelloWorld.sayHello()){
System.out.println("開始事務。。。");
proceed();
System.out.println("結束事務。。。");
}
}
複製代碼
上面的 TxAspect 根本不是一個 Java 類,因此 aspect 也不是 Java 支持的關鍵字,它只是 AspectJ 才能識別的關鍵字。 其後綴爲.aj
,該文件的完整文件名爲TxAspect.aj
。切面的語法只有AspectJ
能夠識別,並使用其特殊的編譯器ajc
來編譯。
這段代碼攔截Hello.sayHello()
方法,並在其執行以前開始事務,proceed()
方法表明回調原來的sayHello()
方法,執行結束後結束事務。
執行結果爲:
開始事務。。。
Hello AspectJ
結束事務。。。
複製代碼
從上面運行結果來看,咱們徹底能夠不對 HelloWorld.java
類進行任何修改,就給它插入了事務管理的功能,這正是面向切面編程的意義所在。從這個例子中咱們也能夠體會到 AspectJ 的易學易用、無侵入(不須要繼承任何類和接口)的特性。
除了上述事務管理的功能,還能夠在 sayHello()
方法後增長記錄日誌的功能。咱們再定義一個 LogAspect,
LogAspect.aj
public aspect LogAspect {
// 定義一個 PointCut,其名爲 logPointcut
// 該 PointCut 對應於指定 HelloWorld 對象的 sayHello 方法
pointcut logPointCut():execution(void HelloWorld.sayHello());
// 在 logPointcut 以後執行下面代碼塊
after():logPointCut(){
System.out.println("記錄日誌。。。。");
}
}
複製代碼
上述代碼定義了一個 Pointcut:logPointcut - 等同於執行 HelloWorld 對象的 sayHello()
方法,並指定在 logPointcut 以後執行簡單的代碼塊,也就是說,在 sayHello()
方法以後執行指定代碼塊。
執行結果爲:
開始事務。。。
Hello AspectJ
記錄日誌。。。。
結束事務。。。
複製代碼
從上面運行結果來看,經過使用 AspectJ 提供的 AOP 支持,咱們能夠爲 sayHello() 方法不斷增長新功能。
爲何在對 HelloWorld 類沒有任何修改的前提下,而 HelloWorld 類能不斷地、動態增長新功能呢?這看上去並不符合 Java 基本語法規則啊。實際上咱們可使用 Java 的反編譯工具來反編譯前面程序生成的 HelloWorld.class 文件,發現 HelloWorld.class 文件的代碼以下:
public class HelloWorld {
public HelloWorld() {
}
public void sayHello() {
try {
System.out.println("Hello AspectJ");
} catch (Throwable var2) {
LogAspect.aspectOf().ajc$after$com_msdn_aspectj_LogAspect$1$9e12ed77();
throw var2;
}
LogAspect.aspectOf().ajc$after$com_msdn_aspectj_LogAspect$1$9e12ed77();
}
public static void main(String[] args) {
HelloWorld hello = new HelloWorld();
sayHello_aroundBody1$advice(hello, TxAspect.aspectOf(), (AroundClosure)null);
}
}
複製代碼
不難發現這個 HelloWorld.class 文件不是由原來的 HelloWorld.java 文件編譯獲得的,該 HelloWorld.class 裏新增了不少內容,sayHello() 方法中增長了日誌功能,主方法中增長了事務管理功能——這代表 AspectJ 在編譯時「自動」編譯獲得了一個新類,這個新類加強了原有的 HelloWorld.java 類的功能,所以 AspectJ 一般被稱爲編譯時加強的 AOP 框架。
在進行案例測試的過程當中,遇到了一系列的問題,總結概括以下:
一、安裝 AspectJ 時,我首先安裝的是 aspectj-1.9.2 版本,可是後續實際測試過程當中,因爲在 IDEA 中配置AspectJ編譯器時錯誤致使代碼執行有誤,當時我配置的狀況以下圖所示:
圖中紅框標記處,我覺得是填寫版本號,可是代碼執行以後會報這樣的錯誤:
錯誤信息爲:
Error:ajc: Compliance level '1.8' is incompatible with target level '9'. A compliance level '9' or better is required
複製代碼
緣由:本地使用的 JDK 版本爲 1.8,此處若是配置1.9的話,會致使 Javac 編譯器配置也發生變化,致使錯誤發生。
因此這也是爲啥我改成安裝 aspectj-1.8.14,當時覺得須要和 JDK 版本統一。可是實際上圖中紅框標識處根本不須要填寫內容。以下圖所示:
二、執行過程當中遇到這樣的錯誤,錯誤信息以下:
Error: java: Compliance level '1.6' is incompatible with target level '1.8'. A compliance level '1.8' or better is required
複製代碼
點擊 File 標籤裏的 Project Structure,選擇 Project Settings->Modules,選擇1.8版本對應的 language level。