Java的Spring框架下的AOP編程模式示例
Spring框架的關(guān)鍵組件是面向方面編程(AOP)框架。面向方面的編程不僅打破程序邏輯分成不同的部分稱(chēng)為所謂的擔(dān)憂??缭蕉鄠€(gè)點(diǎn)的應(yīng)用程序的功能被稱(chēng)為橫切關(guān)注點(diǎn)和這些橫切關(guān)注點(diǎn)是從應(yīng)用程序的業(yè)務(wù)邏輯概念上區(qū)分開(kāi)來(lái)。還有像日志記錄,審計(jì),聲明性事務(wù),安全性和高速緩存等方面的各種常見(jiàn)的好例子
模塊化的OOP中的關(guān)鍵單元是類(lèi),而在AOP中模塊化的單元?jiǎng)t是切面。依賴注入可以幫助你從對(duì)方解耦應(yīng)用程序?qū)ο蠛虯OP可以幫助你從他們影響的對(duì)象分離橫切關(guān)注點(diǎn)。 AOP是一樣的編程語(yǔ)言如Perl,.NET,Java和其他觸發(fā)器。
Spring AOP模塊提供了攔截器攔截的應(yīng)用程序,例如,執(zhí)行一個(gè)方法時(shí),可以之前或之后執(zhí)行的方法添加額外的功能。
AOP術(shù)語(yǔ):
在我們開(kāi)始使用AOP之前,先熟悉AOP的概念和術(shù)語(yǔ)。這些條款是不特定于Spring,問(wèn)題都是有關(guān)AOP。
建議的類(lèi)型
Spring方面可以用5種下面提到的建議:
自定義方面實(shí)現(xiàn)
Spring基于XML模式的AOP
需要如下所述導(dǎo)入Spring AOP架構(gòu):
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <!-- bean definition & AOP specific configuration --> </beans>
還需要在以下應(yīng)用程序CLASSPATH中的AspectJ庫(kù)。這些庫(kù)可以在AspectJ的安裝'lib'目錄可用,可以從互聯(lián)網(wǎng)上下載它們。
- aspectjrt.jar
- aspectjweaver.jar
- aspectj.jar
聲明一個(gè)切面
一個(gè)方面是使用<aop:aspect>元素中聲明,并且支持bean是使用ref屬性如下參考:
<aop:config> <aop:aspect id="myAspect" ref="aBean"> ... </aop:aspect> </aop:config> <bean id="aBean" class="..."> ... </bean>
這里的“aBean”將配置和依賴注入,就像任何其他的Spring bean,我們已經(jīng)在前面的章節(jié)看到。
聲明一個(gè)切入點(diǎn)
一個(gè)切入點(diǎn)有助于確定與不同要執(zhí)行的連接點(diǎn)的利息(即方法)。同時(shí)與XML架構(gòu)基礎(chǔ)的配置工作,切入點(diǎn)將被定義如下:
<aop:config> <aop:aspect id="myAspect" ref="aBean"> <aop:pointcut id="businessService" expression="execution(* com.xyz.myapp.service.*.*(..))"/> ... </aop:aspect> </aop:config> <bean id="aBean" class="..."> ... </bean>
下面的示例定義一個(gè)名為'的businessService“切入點(diǎn)將匹配可用的軟件包c(diǎn)om.yiibai下執(zhí)行g(shù)etName()方法在Student類(lèi):
<aop:config> <aop:aspect id="myAspect" ref="aBean"> <aop:pointcut id="businessService" expression="execution(* com.yiibai.Student.getName(..))"/> ... </aop:aspect> </aop:config> <bean id="aBean" class="..."> ... </bean>
聲明建議
可以聲明任意五個(gè)建議的使用<aop:{ADVICE NAME}>元素下面給出一個(gè)<aop:aspect>內(nèi):
<aop:config> <aop:aspect id="myAspect" ref="aBean"> <aop:pointcut id="businessService" expression="execution(* com.xyz.myapp.service.*.*(..))"/> <!-- a before advice definition --> <aop:before pointcut-ref="businessService" method="doRequiredTask"/> <!-- an after advice definition --> <aop:after pointcut-ref="businessService" method="doRequiredTask"/> <!-- an after-returning advice definition --> <!--The doRequiredTask method must have parameter named retVal --> <aop:after-returning pointcut-ref="businessService" returning="retVal" method="doRequiredTask"/> <!-- an after-throwing advice definition --> <!--The doRequiredTask method must have parameter named ex --> <aop:after-throwing pointcut-ref="businessService" throwing="ex" method="doRequiredTask"/> <!-- an around advice definition --> <aop:around pointcut-ref="businessService" method="doRequiredTask"/> ... </aop:aspect> </aop:config> <bean id="aBean" class="..."> ... </bean>
可以使用相同的doRequiredTask或不同的方法針對(duì)不同的建議。這些方法將被定義為縱橫模塊的一部分。
基于XML模式的AOP例
要理解上述關(guān)系到XML模式的AOP提到的概念,讓我們寫(xiě)這將實(shí)現(xiàn)幾個(gè)建議的一個(gè)例子。
這里是Logging.java文件的內(nèi)容。這實(shí)際上是縱橫模塊的一個(gè)示例,它定義的方法被調(diào)用的各個(gè)點(diǎn)。
package com.yiibai; public class Logging { /** * This is the method which I would like to execute * before a selected method execution. */ public void beforeAdvice(){ System.out.println("Going to setup student profile."); } /** * This is the method which I would like to execute * after a selected method execution. */ public void afterAdvice(){ System.out.println("Student profile has been setup."); } /** * This is the method which I would like to execute * when any method returns. */ public void afterReturningAdvice(Object retVal){ System.out.println("Returning:" + retVal.toString() ); } /** * This is the method which I would like to execute * if there is an exception raised. */ public void AfterThrowingAdvice(IllegalArgumentException ex){ System.out.println("There has been an exception: " + ex.toString()); } }
以下是Student.java文件的內(nèi)容:
package com.yiibai; public class Student { private Integer age; private String name; public void setAge(Integer age) { this.age = age; } public Integer getAge() { System.out.println("Age : " + age ); return age; } public void setName(String name) { this.name = name; } public String getName() { System.out.println("Name : " + name ); return name; } public void printThrowException(){ System.out.println("Exception raised"); throw new IllegalArgumentException(); } }
以下是MainApp.java文件的內(nèi)容:
package com.yiibai; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); Student student = (Student) context.getBean("student"); student.getName(); student.getAge(); student.printThrowException(); } }
以下是配置文件beans.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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id="log" ref="logging"> <aop:pointcut id="selectAll" expression="execution(* com.yiibai.*.*(..))"/> <aop:before pointcut-ref="selectAll" method="beforeAdvice"/> <aop:after pointcut-ref="selectAll" method="afterAdvice"/> <aop:after-returning pointcut-ref="selectAll" returning="retVal" method="afterReturningAdvice"/> <aop:after-throwing pointcut-ref="selectAll" throwing="ex" method="AfterThrowingAdvice"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id="student" class="com.yiibai.Student"> <property name="name" value="Zara" /> <property name="age" value="11"/> </bean> <!-- Definition for logging aspect --> <bean id="logging" class="com.yiibai.Logging"/> </beans>
創(chuàng)建源代碼和bean配置文件完成后,讓我們運(yùn)行應(yīng)用程序。如果一切順利,這將打印以下信息:
Going to setup student profile. Name : Zara Student profile has been setup. Returning:Zara Going to setup student profile. Age : 11 Student profile has been setup. Returning:11 Going to setup student profile. Exception raised Student profile has been setup. There has been an exception: java.lang.IllegalArgumentException ..... other exception content
解釋一下,上面定義<aop:pointcut>選擇所有的包c(diǎn)om.yiibai下定義的方法。讓我們假設(shè),想有一個(gè)特定的方法之前或之后執(zhí)行意見(jiàn),可以定義切入點(diǎn)與實(shí)際的類(lèi)和方法的名稱(chēng)取代星號(hào)(*)的切入點(diǎn)定義來(lái)縮小執(zhí)行。下面是修改后的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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id="log" ref="logging"> <aop:pointcut id="selectAll" expression="execution(* com.yiibai.Student.getName(..))"/> <aop:before pointcut-ref="selectAll" method="beforeAdvice"/> <aop:after pointcut-ref="selectAll" method="afterAdvice"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id="student" class="com.yiibai.Student"> <property name="name" value="Zara" /> <property name="age" value="11"/> </bean> <!-- Definition for logging aspect --> <bean id="logging" class="com.yiibai.Logging"/> </beans>
如果執(zhí)行這些配置更改的示例應(yīng)用程序,這將打印以下信息:
Going to setup student profile. Name : Zara Student profile has been setup. Age : 11 Exception raised ..... other exception content
基于@AspectJ的AOP
@ AspectJ是指聲明方面的風(fēng)格注釋的使用Java 5注釋普通的Java類(lèi)。對(duì)@ AspectJ支持由包括您基于XML Schema的配置文件里面的下列元素啟用。
<aop:aspectj-autoproxy/>
您還需要在以下應(yīng)用程序的類(lèi)路徑中的AspectJ庫(kù)。這些庫(kù)可以在AspectJ的安裝的'lib'目錄,可以從網(wǎng)上下載他們.
- aspectjrt.jar
- aspectjweaver.jar
- aspectj.jar
聲明一個(gè)切面
方面類(lèi)是像任何其他普通的bean,并可能有方法和字段,就像任何其他類(lèi),但他們將被標(biāo)注了@Aspect 如下:
package org.xyz; import org.aspectj.lang.annotation.Aspect; @Aspect public class AspectModule { }
他們將在XML中進(jìn)行配置像任何其他的bean,如下所示:
<bean id="myAspect" class="org.xyz.AspectModule"> <!-- configure properties of aspect here as normal --> </bean>
聲明一個(gè)切入點(diǎn)
一個(gè)切入點(diǎn)有助于確定與不同意見(jiàn)要執(zhí)行的連接點(diǎn)的權(quán)益(即方法)。同時(shí)用@AspectJ的基礎(chǔ)配置工作,切入點(diǎn)聲明有兩個(gè)部分:
切入點(diǎn)表達(dá)式,決定哪些方法執(zhí)行我們感興趣
一個(gè)切入點(diǎn)簽名的包含名字和任意數(shù)量的參數(shù)。該方法的實(shí)際主體是不相關(guān)的,實(shí)際上應(yīng)為空。
下面的示例定義一個(gè)名為'businessService“切入點(diǎn)將匹配每個(gè)方法的可用包c(diǎn)om.xyz.myapp.service下執(zhí)行中的類(lèi):
import org.aspectj.lang.annotation.Pointcut; @Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression private void businessService() {} // signature
下面的示例定義一個(gè)名為'getName'切入點(diǎn)將匹配可用的軟件包c(diǎn)om.yiibai下執(zhí)行g(shù)etName()方法在Student類(lèi):
import org.aspectj.lang.annotation.Pointcut; @Pointcut("execution(* com.yiibai.Student.getName(..))") private void getname() {}
聲明建議
可以聲明任何使用 @{ADVICE-NAME} 注釋下面給出的五個(gè)建議。這假定已經(jīng)定義了一個(gè)切入點(diǎn)簽名的方法的businessService():
@Before("businessService()") public void doBeforeTask(){ ... } @After("businessService()") public void doAfterTask(){ ... } @AfterReturning(pointcut = "businessService()", returning="retVal") public void doAfterReturnningTask(Object retVal){ // you can intercept retVal here. ... } @AfterThrowing(pointcut = "businessService()", throwing="ex") public void doAfterThrowingTask(Exception ex){ // you can intercept thrown exception here. ... } @Around("businessService()") public void doAroundTask(){ ... }
可以定義內(nèi)置切入點(diǎn)的任何意見(jiàn)的。下面是一個(gè)例子定義內(nèi)聯(lián)的切入點(diǎn)之前的建議:
@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
...
}
@AspectJ 基于AOP例子
要理解上述關(guān)系到@AspectJ的AOP的基礎(chǔ)概念提到,讓我們寫(xiě)這將實(shí)現(xiàn)幾個(gè)建議的一個(gè)例子。
這里是Logging.java文件的內(nèi)容。這實(shí)際上是方面模塊的一個(gè)示例,它定義的方法被調(diào)用的各個(gè)點(diǎn)。
package com.yiibai; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Around; @Aspect public class Logging { /** Following is the definition for a pointcut to select * all the methods available. So advice will be called * for all the methods. */ @Pointcut("execution(* com.yiibai.*.*(..))") private void selectAll(){} /** * This is the method which I would like to execute * before a selected method execution. */ @Before("selectAll()") public void beforeAdvice(){ System.out.println("Going to setup student profile."); } /** * This is the method which I would like to execute * after a selected method execution. */ @After("selectAll()") public void afterAdvice(){ System.out.println("Student profile has been setup."); } /** * This is the method which I would like to execute * when any method returns. */ @AfterReturning(pointcut = "selectAll()", returning="retVal") public void afterReturningAdvice(Object retVal){ System.out.println("Returning:" + retVal.toString() ); } /** * This is the method which I would like to execute * if there is an exception raised by any method. */ @AfterThrowing(pointcut = "selectAll()", throwing = "ex") public void AfterThrowingAdvice(IllegalArgumentException ex){ System.out.println("There has been an exception: " + ex.toString()); } }
以下是Student.java文件的內(nèi)容:
package com.yiibai; public class Student { private Integer age; private String name; public void setAge(Integer age) { this.age = age; } public Integer getAge() { System.out.println("Age : " + age ); return age; } public void setName(String name) { this.name = name; } public String getName() { System.out.println("Name : " + name ); return name; } public void printThrowException(){ System.out.println("Exception raised"); throw new IllegalArgumentException(); } }
以下是MainApp.java文件的內(nèi)容:
package com.yiibai; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); Student student = (Student) context.getBean("student"); student.getName(); student.getAge(); student.printThrowException(); } }
以下是配置文件beans.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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:aspectj-autoproxy/> <!-- Definition for student bean --> <bean id="student" class="com.yiibai.Student"> <property name="name" value="Zara" /> <property name="age" value="11"/> </bean> <!-- Definition for logging aspect --> <bean id="logging" class="com.yiibai.Logging"/> </beans>
創(chuàng)建源程序和bean配置文件完成后,讓我們運(yùn)行應(yīng)用程序。如果一切順利,這將打印以下信息:
Going to setup student profile. Name : Zara Student profile has been setup. Returning:Zara Going to setup student profile. Age : 11 Student profile has been setup. Returning:11 Going to setup student profile. Exception raised Student profile has been setup. There has been an exception: java.lang.IllegalArgumentException ..... other exception content
- Spring AOP日志框架實(shí)現(xiàn)過(guò)程圖解
- Spring AspectJ AOP框架注解原理解析
- Spring框架基于AOP實(shí)現(xiàn)簡(jiǎn)單日志管理步驟解析
- Spring框架實(shí)現(xiàn)AOP添加日志記錄功能過(guò)程詳解
- 在Spring Boot框架中使用AOP的正確姿勢(shì)
- 實(shí)例講解Java的Spring框架中的AOP實(shí)現(xiàn)
- Java的Spring框架中AOP項(xiàng)目的一般配置和部署教程
- 舉例講解Java的Spring框架中AOP程序設(shè)計(jì)方式的使用
- Spring框架學(xué)習(xí)之AOP詳解
相關(guān)文章
Linux(centos7)安裝jdk1.8的詳細(xì)步驟
Linux的使用相信大家都要用到j(luò)ava吧,在使用java前我們得先安裝jdk以及配置環(huán)境變量等工作,下面這篇文章主要給大家介紹了關(guān)于Linux(centos7)安裝jdk1.8的詳細(xì)步驟,需要的朋友可以參考下2023-10-10詳解IDEA中Debug的使用和進(jìn)制轉(zhuǎn)換問(wèn)題
這篇文章主要介紹了IDEA中Debug的使用和進(jìn)制轉(zhuǎn)換,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11簡(jiǎn)單了解Java關(guān)鍵字throw和throws的區(qū)別
這篇文章主要介紹了簡(jiǎn)單了解Java關(guān)鍵字throw和throws的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11如何使用Spring AOP的通知類(lèi)型及創(chuàng)建通知
這篇文章主要給大家介紹了關(guān)于如何使用Spring AOP的通知類(lèi)型及創(chuàng)建通知的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring AOP具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12在Java中使用redisTemplate操作緩存的方法示例
這篇文章主要介紹了在Java中使用redisTemplate操作緩存的方法示例,在Redis中可以存儲(chǔ)String、List、Set、Hash、Zset。感興趣的可以了解一下2019-01-01二種jar包制作方法講解(dos打包jar eclipse打包jar文件)
這篇文章主要介紹了二種jar包制作方法講解:dos打包jar和eclipse打包jar文件,大家參考使用吧2013-11-11