一文詳解Spring?AOP的配置與使用
1.關(guān)于AOP
面向切面編程(俗稱AOP)提供了一種面向?qū)ο缶幊?俗稱OOP)的補(bǔ)充,面向?qū)ο缶幊套詈诵牡膯卧穷?class),然而面向切面編程最核心的單元是切面(Aspects)。與面向?qū)ο蟮捻樞蛄鞒滩煌珹OP采用的是橫向切面的方式,注入與主業(yè)務(wù)流程無(wú)關(guān)的功能,例如事務(wù)管理和日志管理。
圖示:
Spring的一個(gè)關(guān)鍵組件是AOP框架。 雖然Spring IoC容器不依賴于AOP(意味著你不需要在IOC中依賴AOP),但AOP為Spring IoC提供了非常強(qiáng)大的中間件解決方案。
AOP 是一種編程范式,最早由 AOP 聯(lián)盟的組織提出的,通過(guò)預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。它是 OOP的延續(xù)。利用 AOP 可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率
2.初步使用AOP環(huán)境配置
要使用Spring AOP,需要導(dǎo)入如下的maven包:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.23</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.9.1</version> </dependency>
在對(duì)應(yīng)的Spring配置文件中,需要導(dǎo)入aop的約束:
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
整體的配置如下:
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> ???????</beans>
編寫接口類:UserService.java
public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
接口實(shí)現(xiàn)類:UserServiceImpl.java
public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("增加用戶"); } @Override public void delete() { System.out.println("刪除用戶"); } @Override public void update() { System.out.println("更新用戶"); } @Override public void query() { System.out.println("查找用戶"); } }
待插入的前置日志類:Log.java
/** * 插入的前置日志類 */ public class Log implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName() + "的" + method.getName() + "被執(zhí)行了!"); } }
待插入的后置日志類:AfterLog.java
/** * 插入的后置日志類 */ public class AfterLog implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("執(zhí)行了" + method.getName() + "方法,返回結(jié)果為:" + returnValue); } }
注冊(cè)類的bean標(biāo)簽:
<!-- 注冊(cè)測(cè)試bean --> <bean id="userService" class="top.imustctf.service.UserServiceImpl"/> <bean id="log" class="top.imustctf.log.Log"/> <bean id="afterLog" class="top.imustctf.log.AfterLog"/>
3.使用原生Spring API接口實(shí)現(xiàn)AOP
配置aop:
切入點(diǎn)是待切入的方法,使用正則表達(dá)式匹配
執(zhí)行環(huán)繞增加是具體向切入點(diǎn)添加日志的配置
<!-- 配置AOP --> <aop:config> <!-- 配置切入點(diǎn) --> <aop:pointcut id="pointcut" expression="execution(* top.imustctf.service.UserServiceImpl.*(..))"/> <!-- 執(zhí)行環(huán)繞增加 --> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config>
現(xiàn)在來(lái)測(cè)試一下吧:
可以看到,AOP動(dòng)態(tài)代理切入成功了!
@Test public void test() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("userService", UserService.class); userService.add(); // top.imustctf.service.UserServiceImpl的add被執(zhí)行了! // 增加用戶 // 執(zhí)行了add方法,返回結(jié)果為:null }
4.使用自定義類實(shí)現(xiàn)AOP
先Diy一個(gè)切面類:DiyPointCut.java
public class DiyPointCut { public void before() { System.out.println("方法執(zhí)行前"); } public void after() { System.out.println("方法執(zhí)行后"); } }
注冊(cè)diy類并配置切面:
<bean id="diy" class="top.imustctf.diy.DiyPointCut"/> <aop:config> <!-- 定義一個(gè)切面,ref中為要引用的類對(duì)象 --> <aop:aspect ref="diy"> <!-- 配置切入點(diǎn) --> <aop:pointcut id="point" expression="execution(* top.imustctf.service.UserServiceImpl.*(..))"/> <!-- 通知 --> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
來(lái)開始測(cè)試:
@Test public void test() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("userService", UserService.class); userService.add(); // 方法執(zhí)行前 // 增加用戶 // 方法執(zhí)行后 }
5.使用注解實(shí)現(xiàn)AOP
使用注解實(shí)現(xiàn)AOP,它更簡(jiǎn)單,更強(qiáng)大!
在使用注解開發(fā)前,需要在Spring配置文件中開啟動(dòng)態(tài)代理的支持:
<aop:aspectj-autoproxy/>
接下來(lái),使用注解直接開發(fā)AOP類:
@Component @Aspect // 標(biāo)注這個(gè)類是一個(gè)切面 public class AnnotationPointCut { @Before("execution(* top.imustctf.service.UserServiceImpl.*(..))") public void before() { System.out.println("方法執(zhí)行前??!"); } @After("execution(* top.imustctf.service.UserServiceImpl.*(..))") public void after() { System.out.println("方法執(zhí)行后??!"); } }
現(xiàn)在來(lái)測(cè)試一下吧:
@Test public void test() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("userService", UserService.class); userService.add(); // 方法執(zhí)行前??! // 增加用戶 // 方法執(zhí)行后?。? }
到此這篇關(guān)于一文詳解Spring AOP的配置與使用的文章就介紹到這了,更多相關(guān)Spring AOP內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Java實(shí)現(xiàn)簡(jiǎn)單串口通信
這篇文章主要介紹了使用Java實(shí)現(xiàn)簡(jiǎn)單串口通信,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Java中ThreadLocal?導(dǎo)致內(nèi)存?OOM?的原因分析
這篇文章主要介紹了Java中ThreadLocal導(dǎo)致內(nèi)存OOM的原因分析,文章基于Java的相關(guān)內(nèi)容展開ThreadLocal導(dǎo)致內(nèi)存OOM的原因分析,需要的小伙v阿布可以參考一下2022-05-05詳解Java中Comparable和Comparator接口的區(qū)別
這篇文章主要介紹了詳解Java中Comparable和Comparator接口的區(qū)別的相關(guān)資料,希望通過(guò)本文大家能徹底掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09java實(shí)現(xiàn)頁(yè)面多查詢條件必選的統(tǒng)一處理思路
這篇文章主要為大家介紹了java實(shí)現(xiàn)頁(yè)面多查詢條件必選的統(tǒng)一處理思路詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06關(guān)于maven環(huán)境的安裝及maven集成idea環(huán)境的問(wèn)題
Maven 是一個(gè)基于 Java 的工具,所以要做的第一件事情就是安裝 JDK。本文重點(diǎn)給大家介紹關(guān)于maven環(huán)境的安裝及和idea環(huán)境的集成問(wèn)題,感興趣的朋友一起看看吧2021-09-09idea2020導(dǎo)入spring5.1的源碼詳細(xì)教程
這篇文章主要介紹了idea2020導(dǎo)入spring5.1的源碼的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06IDEA簡(jiǎn)單實(shí)現(xiàn)登錄注冊(cè)頁(yè)面
這篇文章主要介紹了IDEA簡(jiǎn)單實(shí)現(xiàn)登錄注冊(cè)頁(yè)面,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12