Spring?AOP配置文件方式入門(mén)教程詳解
一、什么是 AOP?
在學(xué)習(xí) Spring 時(shí),我們常聽(tīng)到 AOP(面向切面編程)。
簡(jiǎn)單來(lái)說(shuō),AOP 就是:
在不改變?cè)袠I(yè)務(wù)代碼的情況下,給程序“加點(diǎn)料”。
例如,我們?cè)诒4嬗脩魰r(shí),想額外加上:
打印日志;
記錄操作時(shí)間;
發(fā)送短信;
或者進(jìn)行事務(wù)控制。
這些跟業(yè)務(wù)無(wú)關(guān)的功能,統(tǒng)一抽取到一個(gè)“切面”里,通過(guò) AOP 技術(shù)“織入”到業(yè)務(wù)方法中,就不用每次都手寫(xiě)一遍啦!
二、AOP 的相關(guān)術(shù)語(yǔ)(一定要理解這幾個(gè)?。?/h2>
| 術(shù)語(yǔ) | 含義 | 舉例 |
|---|---|---|
| Joinpoint(連接點(diǎn)) | 被攔截的方法 | save() 方法 |
| Pointcut(切入點(diǎn)) | 定義要攔截哪些方法 | 只攔截 save() 開(kāi)頭的方法 |
| Advice(通知/增強(qiáng)) | 要做的事情(增強(qiáng)邏輯) | 打印日志、事務(wù)控制 |
| Target(目標(biāo)對(duì)象) | 被代理的業(yè)務(wù)類 | UserServiceImpl |
| Weaving(織入) | 把增強(qiáng)邏輯應(yīng)用到目標(biāo)對(duì)象的過(guò)程 | 運(yùn)行時(shí)動(dòng)態(tài)生成代理 |
| Proxy(代理對(duì)象) | 織入增強(qiáng)后產(chǎn)生的新對(duì)象 | 由 Spring 生成 |
| Aspect(切面) | 切入點(diǎn) + 通知 的組合 | 我們自定義的切面類 |
三、Spring AOP 配置文件方式入門(mén)
下面通過(guò)一個(gè)簡(jiǎn)單的例子演示:
在執(zhí)行 UserServiceImpl.save() 方法之前,打印一句“增強(qiáng)的方法執(zhí)行了…”
創(chuàng)建 Maven 項(xiàng)目并添加依賴
<dependencies>
<!-- Spring 核心容器 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- 日志相關(guān) -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!-- 測(cè)試 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- AOP 相關(guān)依賴 -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.3</version>
</dependency>
</dependencies>
創(chuàng)建業(yè)務(wù)類
UserService.java
package com.qcbyjy.demo2;
public interface UserService {
void save();
}
UserServiceImpl.java
package com.qcbyjy.demo2;
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("業(yè)務(wù)層:保存用戶...");
}
}
創(chuàng)建切面類(增強(qiáng)邏輯)
MyXmlAspect.java
package com.qcbyjy.demo2;
/**
* 自定義切面類 = 切入點(diǎn)(表達(dá)式) + 通知(增強(qiáng)代碼)
*/
public class MyXmlAspect {
// 通知邏輯:增強(qiáng)方法
public void log() {
System.out.println("增強(qiáng)的方法執(zhí)行了...");
}
// 環(huán)繞通知示例
public void aroundLog(org.aspectj.lang.ProceedingJoinPoint pjp) throws Throwable {
System.out.println("環(huán)繞前...");
pjp.proceed(); // 手動(dòng)執(zhí)行目標(biāo)方法
System.out.println("環(huán)繞后...");
}
}
Spring 配置文件(applicationContext_demo2.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">
<!-- 配置業(yè)務(wù)類 -->
<bean id="userService" class="com.qcbyjy.demo2.UserServiceImpl"/>
<!-- 配置切面類 -->
<bean id="myXmlAspect" class="com.qcbyjy.demo2.MyXmlAspect"/>
<!-- 配置 AOP 增強(qiáng) -->
<aop:config>
<aop:aspect ref="myXmlAspect">
<!-- 前置通知:目標(biāo)方法執(zhí)行前增強(qiáng) -->
<aop:before method="log"
pointcut="execution(* com.qcbyjy.demo2.UserServiceImpl.save(..))"/>
</aop:aspect>
</aop:config>
</beans>
測(cè)試類
Demo2.java
package com.qcbyjy.test;
import com.qcbyjy.demo2.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext_demo2.xml")
public class Demo2 {
@Autowired
private UserService userService;
@Test
public void run1() {
userService.save();
}
}
輸出結(jié)果:
增強(qiáng)的方法執(zhí)行了...
業(yè)務(wù)層:保存用戶...
說(shuō)明 AOP 生效啦 ??
四、切入點(diǎn)表達(dá)式詳解
AOP 的核心是 切入點(diǎn)表達(dá)式,用來(lái)告訴 Spring 哪些方法要被增強(qiáng)。
基本格式:
execution([修飾符] 返回值類型 包名.類名.方法名(參數(shù)))
示例說(shuō)明:
| 表達(dá)式 | 含義 |
|---|---|
execution(public void com.qcbyjy.demo2.UserServiceImpl.save()) | 精確匹配 |
execution(* com.qcbyjy.*.*ServiceImpl.*(..)) | 模糊匹配所有 ServiceImpl 的任意方法 |
execution(* com.qcbyjy.demo2.*.save*(..)) | 匹配 demo2 包下所有以 save 開(kāi)頭的方法 |
通配符規(guī)則:
*代表任意(一個(gè))內(nèi)容..代表任意包或任意參數(shù)
例如:
<aop:before method="log"
pointcut="execution(* com.qcbyjy.*.*ServiceImpl.save*(..))"/>
表示:增強(qiáng)所有以 save 開(kāi)頭的方法。
五、AOP 的五種通知類型
| 通知類型 | 執(zhí)行時(shí)機(jī) | XML 配置標(biāo)簽 |
|---|---|---|
| 前置通知 | 目標(biāo)方法執(zhí)行前 | <aop:before> |
| 后置通知 | 方法成功執(zhí)行后 | <aop:after-returning> |
| 異常通知 | 方法拋出異常后 | <aop:after-throwing> |
| 最終通知 | 不管成功或失敗都會(huì)執(zhí)行 | <aop:after> |
| 環(huán)繞通知 | 方法執(zhí)行前后都能增強(qiáng)(最靈活) | <aop:around> |
六、環(huán)繞通知示例
<aop:around method="aroundLog"
pointcut="execution(* com.qcbyjy.*.*ServiceImpl.save*(..))" />
執(zhí)行順序:
環(huán)繞前...
增強(qiáng)的方法執(zhí)行了...
業(yè)務(wù)層:保存用戶...
環(huán)繞后...
總結(jié)
| 概念 | 功能 |
|---|---|
| AOP | 把公共功能(如日志、事務(wù))從業(yè)務(wù)邏輯中分離出來(lái) |
| 切面類(Aspect) | 定義要增強(qiáng)的邏輯 |
| 切入點(diǎn)(Pointcut) | 定義哪些方法會(huì)被增強(qiáng) |
| 通知(Advice) | 什么時(shí)候增強(qiáng)(前置、后置、環(huán)繞等) |
| 代理對(duì)象(Proxy) | Spring 自動(dòng)幫我們生成的“帶增強(qiáng)”的對(duì)象 |
通過(guò)這套機(jī)制,Spring AOP 讓你的代碼更清爽、可維護(hù)性更高。
到此這篇關(guān)于Spring AOP配置文件方式入門(mén)教程的文章就介紹到這了,更多相關(guān)Spring AOP配置文件方式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring注解驅(qū)動(dòng)之ApplicationListener用法解讀
這篇文章主要介紹了Spring注解驅(qū)動(dòng)之ApplicationListener用法解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
詳細(xì)理解JAVA面向?qū)ο蟮姆庋b,繼承,多態(tài),抽象
這篇文章主要介紹了Java基礎(chǔ)之面向?qū)ο髾C(jī)制(多態(tài)、繼承)底層實(shí)現(xiàn),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-07-07
SpringBoot多環(huán)境配置數(shù)據(jù)讀取方式
SpringBoot通過(guò)環(huán)境隔離機(jī)制,支持properties/yaml/yml多格式配置,結(jié)合@Value、Environment和@ConfigurationProperties實(shí)現(xiàn)靈活配置讀取,下面給大家介紹SpringBoot之多環(huán)境配置全解析,感興趣的朋友一起看看吧2025-07-07
springboot統(tǒng)一異常處理(返回json)并格式化異常
這篇文章主要介紹了springboot統(tǒng)一異常處理(返回json)并格式化異常,對(duì)spring boot的默認(rèn)異常處理方式進(jìn)行修改,要統(tǒng)一返回?cái)?shù)據(jù)格式,優(yōu)雅的數(shù)據(jù)交互,優(yōu)雅的開(kāi)發(fā)應(yīng)用,需要的朋友可以參考下2023-07-07
Spring Boot項(xiàng)目如何同時(shí)支持HTTP和HTTPS協(xié)議的實(shí)現(xiàn)
這篇文章主要介紹了Spring Boot項(xiàng)目如何同時(shí)支持HTTP和HTTPS協(xié)議的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
基于SpringBoot與Vue開(kāi)發(fā)Web版SQL執(zhí)行工具
這篇文章主要為大家詳細(xì)介紹了一個(gè)基于Web的SQL執(zhí)行工具的設(shè)計(jì)與實(shí)現(xiàn),該工具允許用戶通過(guò)瀏覽器直接執(zhí)行SQL語(yǔ)句并查看結(jié)果,需要的小伙伴可以了解下2025-08-08
詳解Java數(shù)組的一維和二維講解和內(nèi)存顯示圖
這篇文章主要介紹了Java數(shù)組的一維和二維講解和內(nèi)存顯示圖,數(shù)組就相當(dāng)于一個(gè)容器,存放相同類型數(shù)據(jù)的容器。而數(shù)組的本質(zhì)上就是讓我們能 "批量" 創(chuàng)建相同類型的變量,需要的朋友可以參考下2023-05-05
詳解spring開(kāi)發(fā)_JDBC操作MySQL數(shù)據(jù)庫(kù)
本篇文章主要介紹了spring開(kāi)發(fā)_JDBC操作MySQL數(shù)據(jù)庫(kù),具有一定的參考價(jià)值,有興趣的可以了解一下。2016-12-12
java 增強(qiáng)型for循環(huán)語(yǔ)法詳解
增強(qiáng)型 for 循環(huán)(也稱為 “for-each” 循環(huán))是 Java 從 JDK 5 開(kāi)始引入的一種便捷循環(huán)語(yǔ)法,旨在簡(jiǎn)化對(duì)數(shù)組或集合類的迭代操作,這篇文章主要介紹了java 增強(qiáng)型for循環(huán) 詳解,需要的朋友可以參考下2025-04-04

