Spring使用AspectJ注解和XML配置實(shí)現(xiàn)AOP
本文演示的是Spring中使用AspectJ注解和XML配置兩種方式實(shí)現(xiàn)AOP
下面是使用AspectJ注解實(shí)現(xiàn)AOP的Java Project
首先是位于classpath下的applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 啟用AspectJ對(duì)Annotation的支持 -->
<aop:aspectj-autoproxy/>
<bean id="userManager" class="com.jadyer.annotation.UserManagerImpl"/>
<bean id="securityHandler" class="com.jadyer.annotation.SecurityHandler"/>
</beans>
然后是服務(wù)層接口以及實(shí)現(xiàn)類
package com.jadyer.annotation;
public interface UserManager {
public void addUser(String username, String password);
public void delUser(int userId);
public String findUserById(int userId);
public void modifyUser(int userId, String username, String password);
}
/**
* 上面的UserManager是服務(wù)層的接口
* 下面的UserManagerImpl是服務(wù)層接口的實(shí)現(xiàn)類
*/
package com.jadyer.annotation;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
System.out.println("------UserManagerImpl.addUser() is invoked------");
}
public void delUser(int userId) {
System.out.println("------UserManagerImpl.delUser() is invoked------");
}
public String findUserById(int userId) {
System.out.println("------UserManagerImpl.findUserById() is invoked------");
return "鐵面生";
}
public void modifyUser(int userId, String username, String password) {
System.out.println("------UserManagerImpl.modifyUser() is invoked------");
}
}
接下來(lái)是使用AspectJ注解標(biāo)注的切入類
package com.jadyer.annotation;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class SecurityHandler {
/**
* 定義Pointcut
* @see Pointcut的名稱為addAddMethod(),此方法沒(méi)有返回值和參數(shù)
* @see 該方法就是一個(gè)標(biāo)識(shí),不進(jìn)行調(diào)用
*/
@Pointcut("execution(* add*(..))") //匹配所有以add開(kāi)頭的方法
private void addAddMethod(){};
/**
* 定義Advice
* @see 表示我們的Advice應(yīng)用到哪些Pointcut訂閱的Joinpoint上
*/
//@Before("addAddMethod()")
@After("addAddMethod()")
private void checkSecurity() {
System.out.println("------【checkSecurity is invoked】------");
}
}
最后是客戶端測(cè)試類
package com.jadyer.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Spring對(duì)AOP的支持:采用Annotation方式
* @see -------------------------------------------------------------------------------------
* @see Spring提供的AOP功能還是很強(qiáng)大的,支持可配置,它的默認(rèn)實(shí)現(xiàn)使用的就是JDK動(dòng)態(tài)代理
* @see 使用Spring的AOP不需要繼承相關(guān)的東西,也不需要實(shí)現(xiàn)接口
* @see 但有個(gè)前提條件:由于是JDK動(dòng)態(tài)代理,所以若想生成代理,該類就必須得實(shí)現(xiàn)一個(gè)接口才行
* @see 如果該類沒(méi)有implements接口的話,仍去使用Spring的默認(rèn)AOP實(shí)現(xiàn)時(shí),那么就會(huì)出錯(cuò)
* @see 通常需要生成代理的類都是服務(wù)層的類,所以通常都會(huì)抽一個(gè)接口出來(lái)。即養(yǎng)成面向接口編程的習(xí)慣
* @see -------------------------------------------------------------------------------------
* @see 采用Annotation方式完成AOP示例的基本步驟,如下
* @see 1、Spring2.0的依賴包配置。新增Annotation支持
* @see * SPRING_HOME//dist//spring.jar
* @see * SPRING_HOME//lib//log4j//log4j-1.2.14.jar
* @see * SPRING_HOME//lib//jakarta-commons//commons-logging.jar
* @see * SPRING_HOME//lib//aspectj//*.jar
* @see 2、將橫切性關(guān)注點(diǎn)模塊化,建立SecurityHandler.java
* @see 3、采用注解指定SecurityHandler為Aspect
* @see 4、采用注解定義Advice和Pointcut
* @see 5、啟用AspectJ對(duì)Annotation的支持,并且將目標(biāo)類和Aspect類配置到IoC容器中
* @see 6、開(kāi)發(fā)客戶端
* @see -------------------------------------------------------------------------------------
*/
public class Client {
public static void main(String[] args) {
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
UserManager userManager = (UserManager)factory.getBean("userManager");
userManager.addUser("張起靈", "02200059");
}
}
下面是使用XML配置文件實(shí)現(xiàn)AOP的Java Project
首先是位于src根目錄中的applicationContext-cglib.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 強(qiáng)制使用CGLIB代理 -->
<!-- <aop:aspectj-autoproxy proxy-target-class="true"/> -->
<bean id="userManager" class="com.jadyer.cglib.UserManagerImpl"/>
<bean id="securityHandler" class="com.jadyer.cglib.SecurityHandler"/>
<aop:config>
<aop:aspect id="securityAspect" ref="securityHandler">
<aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>
<aop:before method="checkSecurity" pointcut-ref="addAddMethod"/>
</aop:aspect>
</aop:config>
</beans>
<!--
匹配add開(kāi)頭的所有的方法
execution(* add*(..))
匹配com.jadyer.servcices.impl包下的所有的類的所有的方法
execution(* com.jadyer.servcices.impl.*.*(..))
匹配com.jadyer.servcices.impl包下的add或者del開(kāi)頭的所有的方法
execution(* com.jadyer.servcices.impl.*.add*(..)) || execution(* com.jadyer.servcices.impl.*.del*(..))
-->
然后是服務(wù)層接口以及實(shí)現(xiàn)類
package com.jadyer.cglib;
public interface UserManager {
public void addUser(String username, String password);
public void delUser(int userId);
public String findUserById(int userId);
public void modifyUser(int userId, String username, String password);
}
/**
* 上面的UserManager是服務(wù)層接口
* 下面的UserManagerImpl是服務(wù)層接口的實(shí)現(xiàn)類
*/
package com.jadyer.cglib;
public class UserManagerImpl {
//implements UserManager {
public void addUser(String username, String password) {
System.out.println("------UserManagerImpl.addUser() is invoked------");
}
public void delUser(int userId) {
System.out.println("------UserManagerImpl.delUser() is invoked------");
}
public String findUserById(int userId) {
System.out.println("------UserManagerImpl.findUserById() is invoked------");
return "張三";
}
public void modifyUser(int userId, String username, String password) {
System.out.println("------UserManagerImpl.modifyUser() is invoked------");
}
}
接著是在applicationContext-cglib.xml中所指定的切入類
package com.jadyer.cglib;
import org.aspectj.lang.JoinPoint;
/**
* 將客戶調(diào)用信息傳遞到該Advice中
* @see 可以在Advice中添加一個(gè)JoinPoint參數(shù),取得客戶端調(diào)用的方法名稱及參數(shù)值
* @see 以后純粹使用AOP去寫類似這樣?xùn)|西的情況比較少,我們主要使用Spring提供的事務(wù)
* @see 關(guān)于這個(gè),知道即可。下面是示例代碼
*/
public class SecurityHandler {
private void checkSecurity(JoinPoint joinPoint) {
for (int i=0; i<joinPoint.getArgs().length; i++) {
System.out.println(joinPoint.getArgs()[i]); //獲取客戶端調(diào)用的方法的參數(shù)值
}
System.out.println(joinPoint.getSignature().getName()); //獲取客戶端調(diào)用的方法名稱
System.out.println("------【checkSecurity is invoked】------");
}
}
最后是客戶端測(cè)試類
package com.jadyer.cglib;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @see --------------------------------------------------------------------------------------------------
* @see JDK動(dòng)態(tài)代理和CGLIB代理的差別
* @see 1..JDK動(dòng)態(tài)代理對(duì)實(shí)現(xiàn)了接口的類進(jìn)行代理
* @see 2..CGLIB代理可以對(duì)類代理,主要對(duì)指定的類生成一個(gè)子類。由于是繼承,所以目標(biāo)類最好不要使用final聲明
* @see --------------------------------------------------------------------------------------------------
* @see 代理方式的選擇
* @see 1..如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,默認(rèn)情況下會(huì)采用JDK動(dòng)態(tài)代理實(shí)現(xiàn)AOP,亦可強(qiáng)制使用CGLIB生成代理實(shí)現(xiàn)AOP
* @see 2..如果目標(biāo)對(duì)象未實(shí)現(xiàn)接口,那么必須引入CGLIB,這時(shí)Spring會(huì)在JDK動(dòng)態(tài)代理和CGLIB代理之間自動(dòng)切換
* @see 3..比較鼓勵(lì)業(yè)務(wù)對(duì)象是針對(duì)接口編程的,所以鼓勵(lì)使用JDK動(dòng)態(tài)代理。因?yàn)槲覀兯淼哪繕?biāo),一般都是業(yè)務(wù)對(duì)象
* @see --------------------------------------------------------------------------------------------------
* @see 使用CGLIG代理的步驟
* @see 1..新增CGLIB庫(kù):SPRING_HOME//lib//cglib//*.jar
* @see 2..新增配置標(biāo)簽,強(qiáng)制使用CGLIB代理<aop:aspectj-autoproxy proxy-target-class="true"/>
* @see --------------------------------------------------------------------------------------------------
*/
public class Client {
public static void main(String[] args) {
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext-cglib.xml");
//當(dāng)UserManagerImpl實(shí)現(xiàn)了UserManager接口的情況下,這時(shí)Spring會(huì)自動(dòng)使用JDK動(dòng)態(tài)代理
//如果項(xiàng)目已經(jīng)引入cglib庫(kù),并在配置文件中強(qiáng)制使用CGLIB代理,此時(shí)Spring才會(huì)使用CGLIB代理
//UserManager userManager = (UserManager)factory.getBean("userManager");
//由于此時(shí)的UserManagerImpl并沒(méi)有實(shí)現(xiàn)UserManager接口,所以接收類型就不能再使用UserManager接口
//并且項(xiàng)目中已經(jīng)引入了cglib庫(kù),盡管配置文件中沒(méi)有強(qiáng)制使用CGLIB代理,但Spring會(huì)自動(dòng)使用CGLIB代理
UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager");
userManager.addUser("吳三省", "02200059");
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot Websocket Stomp 消息訂閱推送
本文主要介紹了Springboot Websocket Stomp 消息訂閱推送,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07
MybatisPlus自動(dòng)填充時(shí)間的配置類實(shí)現(xiàn)
本文介紹了如何在MyBatis-Plus中實(shí)現(xiàn)自動(dòng)填充時(shí)間的功能,通過(guò)實(shí)現(xiàn)MetaObjectHandler接口,重寫insertFill()和updateFill()方法,分別在插入和更新時(shí)填充創(chuàng)建時(shí)間和更新時(shí)間,感興趣的可以了解一下2024-12-12
幾種JAVA細(xì)粒度鎖的實(shí)現(xiàn)方式
這篇文章主要為大家詳細(xì)介紹了幾種JAVA細(xì)粒度鎖的實(shí)現(xiàn)方式,感興趣的小伙伴們可以參考一下2016-05-05
Java開(kāi)發(fā)崗位面試被問(wèn)到反射怎么辦
這篇文章主要介紹了java 面向?qū)ο竺嬖嚰\的相關(guān)資料,這里整理了面向?qū)ο蟮幕A(chǔ)知識(shí),幫助大家學(xué)習(xí)理解此部分的知識(shí),需要的朋友可以參考下2021-07-07
java應(yīng)用開(kāi)發(fā)之JVM運(yùn)行時(shí)內(nèi)存分析
這篇文章主要介紹了java應(yīng)用開(kāi)發(fā)之JVM運(yùn)行時(shí)內(nèi)存,文中附含圖文示例內(nèi)容分析非常簡(jiǎn)要,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-09-09
JPA如何使用nativequery多表關(guān)聯(lián)查詢返回自定義實(shí)體類
這篇文章主要介紹了JPA如何使用nativequery多表關(guān)聯(lián)查詢返回自定義實(shí)體類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java中l(wèi)ength,length(),size()詳解及區(qū)別
這篇文章主要介紹了Java中l(wèi)ength,length(),size()詳解及區(qū)別的相關(guān)資料,需要的朋友可以參考下2016-11-11
關(guān)于Springboot的擴(kuò)展點(diǎn)DisposableBean的原理解析
這篇文章主要介紹了關(guān)于Springboot的擴(kuò)展點(diǎn)DisposableBean的原理解析,DisposableBean是一個(gè)接口,為Spring bean提供了一種釋放資源的方式 ,只有一個(gè)擴(kuò)展方法destroy(),需要的朋友可以參考下2023-05-05
mybatis的動(dòng)態(tài)SQL和模糊查詢實(shí)例詳解
這篇文章主要給大家介紹了關(guān)于mybatis的動(dòng)態(tài)SQL和模糊查詢的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03

