Spring boot AOP通過(guò)XML配置文件聲明的方法
通過(guò) XML 配置文件聲明
在前兩篇博文和示例中,我們已經(jīng)展示了如何通過(guò)注解配置去聲明切面,下面我們看看如何在 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 | 定義一個(gè)切面 |
| aop:aspectj-autoproxy | 啟用@AspectJ注解驅(qū)動(dòng)的切面 |
| aop:before | 定義一個(gè)AOP前置通知 |
| aop:config | 頂層的AOP配置元素。大多數(shù)的aop:*元素必須包含在aop:config元素內(nèi) |
| aop:declare-parents | 以透明的方式為被通知的對(duì)象引入額外的接口 |
| aop:pointcut | 定義一個(gè)切點(diǎn) |
XML 配置文件中切點(diǎn)指示器
在XML配置文件中,切點(diǎn)指示器表達(dá)式與通過(guò)注解配置的寫(xiě)法基本一致,區(qū)別前面有提到,即XML文件中需要使用 “and”、“or”、“not”來(lái)表示 “且”、“或”、“非”的關(guān)系。
XML 文件配置 AOP
新建OrderXmlAop.java:
package com.example.demo.aop;
public class OrderXmlAop {
/**
* @description 在連接點(diǎn)執(zhí)行之前執(zhí)行的通知
*/
public void doBefore(){
System.out.println("阿里阿塞喲!");
}
/**
* @description 在連接點(diǎn)執(zhí)行之后執(zhí)行的通知(返回通知和異常通知的異常)
*/
public void doAfter(){
System.out.println("after!");
}
/**
* @description 在連接點(diǎn)執(zhí)行之后執(zhí)行的通知(返回通知)
*/
public void doAfterReturning(){
System.out.println("返回通知:AfterReturning");
}
/**
* @description 在連接點(diǎn)執(zhí)行之后執(zhí)行的通知(異常通知)
*/
public void doAfterThrowing(){
System.out.println("異常通知:AfterThrowing");
}
}
在 Resource 目錄下新建一個(gè)配置文件 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> <!-- 切面類(lèi) --> <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é)點(diǎn)上的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);
}
}
運(yùn)行結(jié)果:

聲明環(huán)繞通知
修改OrderXmlAop.java:
package com.example.demo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
public class OrderXmlAop {
/**
* @description 在連接點(diǎn)執(zhí)行之前執(zhí)行的通知
*/
public void doBefore(){
System.out.println("阿里阿塞喲!");
}
/**
* @description 在連接點(diǎn)執(zhí)行之后執(zhí)行的通知(返回通知和異常通知的異常)
*/
public void doAfter(){
System.out.println("after!");
}
/**
* @description 在連接點(diǎn)執(zhí)行之后執(zhí)行的通知(返回通知)
*/
public void doAfterReturning(){
System.out.println("返回通知:AfterReturning");
}
/**
* @description 在連接點(diǎn)執(zhí)行之后執(zhí)行的通知(異常通知)
*/
public void doAfterThrowing(){
System.out.println("異常通知:AfterThrowing");
}
/**
* @description 在連接點(diǎn)執(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> <!-- 切面類(lèi) --> <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>
運(yùn)行結(jié)果:

結(jié)果和我們預(yù)期的一致,環(huán)繞通知通過(guò)xml配置成功。
XML 文件配置聲明切點(diǎn)
在上面的例子中,我們發(fā)現(xiàn)有切點(diǎn)表達(dá)式多次重復(fù)出現(xiàn),那么可不可以和aspectj配置一樣,單獨(dú)聲明切點(diǎn),后面復(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> <!-- 切面類(lèi) --> <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean> <!-- Aop配置 --> <aop:config proxy-target-class="true"> <!-- 切點(diǎn) --> <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下單超過(guò)了4399,贈(zèng)送一份鮮果飲匯源牌飲料");
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> <!-- 切面類(lèi) --> <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean> <!-- Aop配置 --> <aop:config proxy-target-class="true"> <!-- 切點(diǎn) --> <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é)
本文主要通過(guò)XML配置文件使用 Spring AOP進(jìn)行編程,和上一篇的注解方式兩者聯(lián)系起來(lái)對(duì)于剛?cè)腴T(mén)的應(yīng)該多多少少還是有點(diǎn)幫助的吧,針對(duì)于aop 通過(guò)三篇博客簡(jiǎn)單的描述,相信大家對(duì)此都有點(diǎn)印象了,記錄了 AOP 的編程思想,然后介紹了 Spring 中 AOP 的相關(guān)概念,以及通過(guò)注解方式和XML配置文件兩種方式使用 Spring AOP進(jìn)行編程。所以對(duì)aop的博文就簡(jiǎn)單到這兒了,有人要問(wèn)了,aop里面的代理啊還有各種各樣的,如果真要吧aop重頭到尾來(lái)一遍的話(huà),這個(gè)系列可以單獨(dú)提出來(lái)一個(gè)專(zhuān)欄了,所以后面的博文應(yīng)該都是圍繞連接數(shù)據(jù)庫(kù),記錄日志,接入swagger文檔等功能相繼展開(kāi)了。在此過(guò)程中,我有錯(cuò)誤使用的地方,或者表達(dá)有問(wèn)題,還請(qǐng)您及時(shí)告知,本人會(huì)在第一時(shí)間予以改正。最后在祝大家周末愉快,C Y L L
相關(guān)文章
Java超詳細(xì)講解接口的實(shí)現(xiàn)與用法
Java接口是一系列方法的聲明,是一些方法特征的集合,一個(gè)接口只有方法的特征沒(méi)有方法的實(shí)現(xiàn),因此這些方法可以在不同的地方被不同的類(lèi)實(shí)現(xiàn),而這些實(shí)現(xiàn)可以具有不同的行為2022-04-04
Java快速入門(mén)掌握類(lèi)與對(duì)象及變量的使用
類(lèi)和對(duì)象是兩種以計(jì)算機(jī)為載體的計(jì)算機(jī)語(yǔ)言的合稱(chēng)。對(duì)象是對(duì)客觀事物的抽象,類(lèi)是對(duì)對(duì)象的抽象。類(lèi)是一種抽象的數(shù)據(jù)類(lèi)型;變量就是可以變化的量,存儲(chǔ)在內(nèi)存中—個(gè)可以擁有在某個(gè)范圍內(nèi)的可變存儲(chǔ)區(qū)域2022-04-04
Java并發(fā)編程之synchronized底層實(shí)現(xiàn)原理分析
這篇文章主要介紹了Java并發(fā)編程之synchronized底層實(shí)現(xiàn)原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
Java File類(lèi)的詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了Java File類(lèi)的詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,希望通過(guò)本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09
SpringBoot整合JPA詳細(xì)代碼實(shí)例
這篇文章主要給大家介紹了關(guān)于SpringBoot整合JPA的相關(guān)資料,JPA(Java Persistence API)是Sun官方提出的Java持久化規(guī)范,它為Java開(kāi)發(fā)人員提供了一種對(duì)象/關(guān)聯(lián)映射工具來(lái)管理Java應(yīng)用中的關(guān)系數(shù)據(jù),需要的朋友可以參考下2024-05-05
使用spring?security?BCryptPasswordEncoder接入系統(tǒng)
這篇文章主要介紹了使用spring?security?BCryptPasswordEncoder接入系統(tǒng)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
詳解Java中static關(guān)鍵字和內(nèi)部類(lèi)的使用
這篇文章主要為大家詳細(xì)介紹了Java中static關(guān)鍵字和內(nèi)部類(lèi)的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-08-08
springcloud config配置讀取優(yōu)先級(jí)過(guò)程詳解
這篇文章主要介紹了springcloud config配置讀取優(yōu)先級(jí)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09

