Spring boot AOP通過XML配置文件聲明的方法
通過 XML 配置文件聲明
在前兩篇博文和示例中,我們已經(jīng)展示了如何通過注解配置去聲明切面,下面我們看看如何在 XML 文件中聲明切面。下面先列出 XML 中聲明 AOP 的常用元素:
| AOP配置元素 | 用途 |
|---|---|
| aop:advisor | 定義AOP通知器 |
| aop:after | 定義AOP后置通知(不管被通知的方法是否執(zhí)行成功) |
| aop:after-returning | 定義AOP返回通知 |
| aop:after-throwing | 定義AOP異常通知 |
| aop:around | 定義AOP環(huán)繞通知 |
| aop:aspect | 定義一個切面 |
| aop:aspectj-autoproxy | 啟用@AspectJ注解驅(qū)動的切面 |
| aop:before | 定義一個AOP前置通知 |
| aop:config | 頂層的AOP配置元素。大多數(shù)的aop:*元素必須包含在aop:config元素內(nèi) |
| aop:declare-parents | 以透明的方式為被通知的對象引入額外的接口 |
| aop:pointcut | 定義一個切點 |
XML 配置文件中切點指示器
在XML配置文件中,切點指示器表達(dá)式與通過注解配置的寫法基本一致,區(qū)別前面有提到,即XML文件中需要使用 “and”、“or”、“not”來表示 “且”、“或”、“非”的關(guān)系。
XML 文件配置 AOP
新建OrderXmlAop.java:
package com.example.demo.aop;
public class OrderXmlAop {
/**
* @description 在連接點執(zhí)行之前執(zhí)行的通知
*/
public void doBefore(){
System.out.println("阿里阿塞喲!");
}
/**
* @description 在連接點執(zhí)行之后執(zhí)行的通知(返回通知和異常通知的異常)
*/
public void doAfter(){
System.out.println("after!");
}
/**
* @description 在連接點執(zhí)行之后執(zhí)行的通知(返回通知)
*/
public void doAfterReturning(){
System.out.println("返回通知:AfterReturning");
}
/**
* @description 在連接點執(zhí)行之后執(zhí)行的通知(異常通知)
*/
public void doAfterThrowing(){
System.out.println("異常通知:AfterThrowing");
}
}
在 Resource 目錄下新建一個配置文件 aoporder.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: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"> <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean> <bean id="zsService" class="com.example.demo.service.impl.ZSServiceImpl"></bean> <!-- 切面類 --> <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean> <!-- Aop配置 --> <aop:config proxy-target-class="true"> <!-- 切面 --> <aop:aspect ref="OrderXmlAop"> <!-- 前置通知: 在目標(biāo)方法調(diào)用前執(zhí)行 --> <aop:before pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doBefore"/> <!-- 后置通知: --> <aop:after pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfter"/> <!-- 返回后通知 --> <aop:after-returning pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfterReturning"/> <!-- 異常通知 --> <aop:after-throwing pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfterThrowing"/> </aop:aspect> </aop:config> </beans>
新建 TakeXmlController.java
package com.example.demo.controller;
import com.example.demo.entity.Response;
import com.example.demo.entity.ResponseResult;
import jdk.internal.org.objectweb.asm.tree.analysis.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.service.TakeawayService;
@RestController
@RequestMapping("/api")
public class TakeXmlController {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aoporder.xml");
@RequestMapping("/orderxml")
public ResponseResult Ordexml()
{
/**
** 注意 此處的getBean(name)中的name 必須要和aoporder.xml 配置的bean節(jié)點上的id 保持一致
* 如: <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean>
* TakeawayService wmzService=(TakeawayService)context.getBean("wmzService");
*/
TakeawayService wmzService=(TakeawayService)context.getBean("wmzService");
String wmz= wmzService.Order(12);
System.out.println(wmz);
TakeawayService zsService=(TakeawayService)context.getBean("zsService");
String zs=zsService.Order(4396);
System.out.println(zs);
return Response.makeOKRsp(wmz+";"+zs);
}
}
運行結(jié)果:

聲明環(huán)繞通知
修改OrderXmlAop.java:
package com.example.demo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
public class OrderXmlAop {
/**
* @description 在連接點執(zhí)行之前執(zhí)行的通知
*/
public void doBefore(){
System.out.println("阿里阿塞喲!");
}
/**
* @description 在連接點執(zhí)行之后執(zhí)行的通知(返回通知和異常通知的異常)
*/
public void doAfter(){
System.out.println("after!");
}
/**
* @description 在連接點執(zhí)行之后執(zhí)行的通知(返回通知)
*/
public void doAfterReturning(){
System.out.println("返回通知:AfterReturning");
}
/**
* @description 在連接點執(zhí)行之后執(zhí)行的通知(異常通知)
*/
public void doAfterThrowing(){
System.out.println("異常通知:AfterThrowing");
}
/**
* @description 在連接點執(zhí)行之后執(zhí)行的通知(異常通知)
*/
public void doAround(ProceedingJoinPoint pj) {
try {
System.out.println("Around 調(diào)用方法前 ");
pj.proceed();
System.out.println("Around 調(diào)用方法后");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
aoporder.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: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"> <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean> <bean id="zsService" class="com.example.demo.service.impl.ZSServiceImpl"></bean> <!-- 切面類 --> <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean> <!-- Aop配置 --> <aop:config proxy-target-class="true"> <!-- 切面 --> <aop:aspect ref="OrderXmlAop"> <!-- 環(huán)繞通知 --> <aop:around pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAround"/> <!-- 前置通知: 在目標(biāo)方法調(diào)用前執(zhí)行 --> <aop:before pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doBefore"/> <!-- 后置通知: --> <aop:after pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfter"/> <!-- 返回后通知 --> <aop:after-returning pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfterReturning"/> <!-- 異常通知 --> <aop:after-throwing pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfterThrowing"/> </aop:aspect> </aop:config> </beans>
運行結(jié)果:

結(jié)果和我們預(yù)期的一致,環(huán)繞通知通過xml配置成功。
XML 文件配置聲明切點
在上面的例子中,我們發(fā)現(xiàn)有切點表達(dá)式多次重復(fù)出現(xiàn),那么可不可以和aspectj配置一樣,單獨聲明切點,后面復(fù)用,答案是當(dāng)然可以。如下修改aoporder.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: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"> <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean> <bean id="zsService" class="com.example.demo.service.impl.ZSServiceImpl"></bean> <!-- 切面類 --> <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean> <!-- Aop配置 --> <aop:config proxy-target-class="true"> <!-- 切點 --> <aop:pointcut id="point" expression="execution(public * com.example.demo.service.TakeawayService.*(..)))"/> <!-- 切面 --> <aop:aspect ref="OrderXmlAop"> <!-- 環(huán)繞通知 --> <aop:around pointcut-ref="point" method="doAround"/> <!-- 前置通知: 在目標(biāo)方法調(diào)用前執(zhí)行 --> <aop:before pointcut-ref="point" method="doBefore"/> <!-- 后置通知: --> <aop:after pointcut-ref="point" method="doAfter"/> <!-- 返回后通知 --> <aop:after-returning pointcut-ref="point" method="doAfterReturning"/> <!-- 異常通知 --> <aop:after-throwing pointcut-ref="point" method="doAfterThrowing"/> </aop:aspect> </aop:config> </beans>
修改后執(zhí)行結(jié)果:

XML文件配置為通知傳遞參數(shù)
修改OrderXmlAop.java
public String doAround(ProceedingJoinPoint pj,double price) {
try {
System.out.println("Around 調(diào)用方法前 ");
pj.proceed();
if(price>=4396)
{
System.out.println("zs下單超過了4399,贈送一份鮮果飲匯源牌飲料");
return "爆漿牛丸和飲料";
}
System.out.println("Around 調(diào)用方法后");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return "爆漿牛丸";
}
修改aoporder.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: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"> <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean> <bean id="zsService" class="com.example.demo.service.impl.ZSServiceImpl"></bean> <!-- 切面類 --> <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean> <!-- Aop配置 --> <aop:config proxy-target-class="true"> <!-- 切點 --> <aop:pointcut id="point" expression="execution(com.example.demo.service.TakeawayService.Order(double)) and args(price) and bean(zsService)"/> <!-- 切面 --> <aop:aspect ref="OrderXmlAop"> <!-- 環(huán)繞通知 --> <aop:around pointcut-ref="point" method="doAround"/> </aop:aspect> </aop:config> </beans>
總結(jié)
本文主要通過XML配置文件使用 Spring AOP進(jìn)行編程,和上一篇的注解方式兩者聯(lián)系起來對于剛?cè)腴T的應(yīng)該多多少少還是有點幫助的吧,針對于aop 通過三篇博客簡單的描述,相信大家對此都有點印象了,記錄了 AOP 的編程思想,然后介紹了 Spring 中 AOP 的相關(guān)概念,以及通過注解方式和XML配置文件兩種方式使用 Spring AOP進(jìn)行編程。所以對aop的博文就簡單到這兒了,有人要問了,aop里面的代理啊還有各種各樣的,如果真要吧aop重頭到尾來一遍的話,這個系列可以單獨提出來一個專欄了,所以后面的博文應(yīng)該都是圍繞連接數(shù)據(jù)庫,記錄日志,接入swagger文檔等功能相繼展開了。在此過程中,我有錯誤使用的地方,或者表達(dá)有問題,還請您及時告知,本人會在第一時間予以改正。最后在祝大家周末愉快,C Y L L
相關(guān)文章
Java運用設(shè)計模式中的建造者模式構(gòu)建項目的實例解析
這篇文章主要介紹了Java運用設(shè)計模式中的建造者模式構(gòu)建項目的實例解析,建造者模式對外隱藏創(chuàng)建過程的產(chǎn)品,使用組合的方式,由指揮者來決定建造的流程,需要的朋友可以參考下2016-04-04
vue數(shù)據(jù)響應(yīng)式原理重寫函數(shù)實現(xiàn)數(shù)組響應(yīng)式監(jiān)聽
Vue的通過數(shù)據(jù)劫持的方式實現(xiàn)數(shù)據(jù)的雙向綁定,即使用Object.defineProperty()來實現(xiàn)對屬性的劫持,但是Object.defineProperty()中的setter是無法直接實現(xiàn)數(shù)組中值的改變的劫持行為的,需要的朋友可以參考下2023-05-05
spring-redis-session 自定義 key 和過期時間
這篇文章主要介紹了spring-redis-session 自定義 key 和過期時間,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
SpringBoot+vue+Axios實現(xiàn)Token令牌的詳細(xì)過程
Token是在服務(wù)端產(chǎn)生的,前端可以使用用戶名/密碼向服務(wù)端請求認(rèn)證(登錄),服務(wù)端認(rèn)證成功,服務(wù)端會返回?Token?給前端,Token可以使用自己的算法自定義,本文給大家介紹SpringBoot+vue+Axios實現(xiàn)Token令牌,感興趣的朋友一起看看吧2023-10-10
SpringBoot通過注解監(jiān)測Controller接口的代碼示例
在Spring Boot中,度量指標(biāo)(Metrics)是監(jiān)控和診斷應(yīng)用性能與行為的重要工具,Spring Boot通過集成Micrometer和Spring Boot Actuator,提供了強(qiáng)大的度量指標(biāo)收集與暴露功能,本文介紹了SpringBoot通過注解監(jiān)測Controller接口,需要的朋友可以參考下2024-07-07

