基于AspectJ實作AOP操作
- 準備作業
- 在專案工程里面引入 AOP 相關依賴,
- 學會使用切入點運算式
- AOP 操作(AspectJ 注解)
- 1、創建類,在類里面定義方法
- 2、創建增強類(撰寫增強邏輯),在增強類里面,創建方法,讓不同方法代表不同通知型別
- 3、進行通知的配置
- 4、配置不同型別的通知
- 相同的切入點抽取
- 有多個增強類多同一個方法進行增強,設定增強類優先級
- 完全使用注解開發
- 代碼結構
- 測驗代碼
Spring 框架一般都是基于 AspectJ 實作 AOP 操作,
需要注意的是:AspectJ 不是 Spring 組成部分,獨立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用,進行 AOP 操作,
基于 AspectJ 實作 AOP 操作有兩種方式:
(1)基于 xml 組態檔實作
(2)基于注解方式實作(普遍使用)
準備作業
在專案工程里面引入 AOP 相關依賴,
需要以下這些依賴:

學會使用切入點運算式
切入點運算式作用(通俗的講):知道對哪個類里面的哪個方法進行增強,
語法結構: execution([權限修飾符] [回傳型別] [類全路徑] [方法名稱] ([引數串列]) )
例 1:對 com.atguigu.dao.BookDao 類里面的 add 進行增強
execution( * com.atguigu.dao.BookDao.add(…))
例 2:對 com.atguigu.dao.BookDao 類里面的所有的方法進行增強
execution( * com.atguigu.dao.BookDao. * (…))
例 3:對 com.atguigu.dao 包里面所有類,類里面所有方法進行增強
execution( * com.atguigu.dao. * . * (…))
AOP 操作(AspectJ 注解)
1、創建類,在類里面定義方法
User類:
package com.Keafmd.spring5.aopanno;
import org.springframework.stereotype.Component;
/**
* Keafmd
*
* @ClassName: User
* @Description: 基于注解 被增強的類
* @author: 牛哄哄的柯南
* @date: 2021-01-18 13:54
*/
@Component
public class User {
public void add(){
// int i = 10/0;
System.out.println("add....");
}
}
2、創建增強類(撰寫增強邏輯),在增強類里面,創建方法,讓不同方法代表不同通知型別
UserProxy 類:
package com.Keafmd.spring5.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* Keafmd
*
* @ClassName: UserPtoxy
* @Description: 增強類
* @author: 牛哄哄的柯南
* @date: 2021-01-18 13:56
*/
@Component
@Aspect //生成代理物件
@Order(3)
public class UserProxy {
//相同的切入點抽取
@Pointcut(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void pointdemo(){
}
//前置通知
//@Before注解就表示前置通知
@Before(value = "pointdemo()")
public void beafor(){
System.out.println("before...");
}
//最終通知
@After(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void after(){
System.out.println("after...");
}
//后置通知(回傳通知)
@AfterReturning(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning...");
}
//例外執行
@AfterThrowing(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing...");
}
//環繞通知
@Around(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("around-before...");
//被增強的方法執行
proceedingJoinPoint.proceed();
System.out.println("around-after...");
}
}
3、進行通知的配置
(1)在 spring 組態檔中,開啟注解掃描
(2)使用注解創建 User 和 UserProxy 物件
(3)在增強類上面添加注解 @Aspect
(4)在 spring 組態檔中開啟生成代理物件
bean2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--開啟注解掃描-->
<context:component-scan base-package="com.Keafmd.spring5.aopanno"></context:component-scan>
<!--開啟AspectJ生成代理物件-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
4、配置不同型別的通知
在增強類的里面,在作為通知方法上面添加通知型別注解,使用切入點運算式配置,
UserProxy 類:
package com.Keafmd.spring5.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* Keafmd
*
* @ClassName: UserPtoxy
* @Description: 增強類
* @author: 牛哄哄的柯南
* @date: 2021-01-18 13:56
*/
@Component
@Aspect //生成代理物件
@Order(3)
public class UserProxy {
//相同的切入點抽取
@Pointcut(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void pointdemo(){
}
//前置通知
//@Before注解就表示前置通知
@Before(value = "pointdemo()")
public void beafor(){
System.out.println("before...");
}
//最終通知
@After(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void after(){
System.out.println("after...");
}
//后置通知(回傳通知)
@AfterReturning(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning...");
}
//例外執行
@AfterThrowing(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing...");
}
//環繞通知
@Around(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("around-before...");
//被增強的方法執行
proceedingJoinPoint.proceed();
System.out.println("around-after...");
}
}
相同的切入點抽取
寫個方法然后呼叫這樣就可以把相同接入點抽取出來了,
//相同的切入點抽取
@Pointcut(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void pointdemo(){
}
//前置通知
//@Before注解就表示前置通知
@Before(value = "pointdemo()")
public void beafor(){
System.out.println("before...");
}
有多個增強類多同一個方法進行增強,設定增強類優先級
在增強類上面添加注解 @Order(數字型別值),數字型別值越小優先級越高,
@Component
@Aspect //生成代理物件
@Order(3)
public class UserProxy {
PersonProxy類:
package com.Keafmd.spring5.aopanno;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* Keafmd
*
* @ClassName: PersonProxy
* @Description: 第二個增強類
* @author: 牛哄哄的柯南
* @date: 2021-01-18 14:39
*/
@Component
@Aspect
@Order(1) //越小優先級越高
public class PersonProxy {
//前置通知
//@Before注解就表示前置通知
@Before(value = "execution(* com.Keafmd.spring5.aopanno.User.add(..))")
public void beafor(){
System.out.println("Person before...");
}
}
通過@Order設定后PersonProxy 的前置通知就會比UserProxy 的前置通知先執行,
完全使用注解開發
創建配置類,這樣就不需要使用 xml 組態檔了,
ConfigAop類:
package com.Keafmd.spring5.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* Keafmd
*
* @ClassName: ConfigAop
* @Description: 配置類,完全注解,替代bean2.xml
* @author: 牛哄哄的柯南
* @date: 2021-01-18 15:12
*/
@Configuration
@ComponentScan(basePackages = {"com.Keafmd"}) //開啟注解掃描
@EnableAspectJAutoProxy(proxyTargetClass = true) //開啟AspectJ生成代理物件
public class ConfigAop {
}
代碼結構

測驗代碼
測驗代碼TestAop:
package com.Keafmd.spring5.test;
import com.Keafmd.spring5.aopanno.User;
import com.Keafmd.spring5.config.ConfigAop;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Keafmd
*
* @ClassName: TestAop
* @Description:
* @author: 牛哄哄的柯南
* @date: 2021-01-18 14:15
*/
public class TestAop {
@Test
public void testAOPnno(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
User user = context.getBean("user",User.class);
user.add();
}
//完全注解
@Test
public void testAOPnno2(){
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigAop.class);
User user = context.getBean("user",User.class);
user.add();
}
}
輸出結果:
Person before...
around-before...
before...
add....
around-after...
after...
afterReturning...
Process finished with exit code 0
testAOPnno和testAOPnno2的結果是相同的testAOPnno2采用是的完全注解開發,代替了xml組態檔,通過運行結果我們可以很輕清楚地看到不同型別通知的執行順序,以及增強類的優先級,
以上就是基于AspectJ實作AOP操作的全部內容,
看完如果對你有幫助,感謝點贊支持!
如果你是電腦端的話,看到右下角的 “一鍵三連” 了嗎,沒錯點它[哈哈]

加油!
共同努力!
Keafmd
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/250666.html
標籤:java
上一篇:goto語法在PHP中的使用
下一篇:Java基礎語法
