本文演示的是Spring中使用AspectJ注解和XML配置兩種方式實現AOP
下面是使用AspectJ注解實現AOP的Java Project
首先是位于classpath下的applicationContext.xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<? 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對Annotation的支持 --> < aop:aspectj-autoproxy /> < bean id = "userManager" class = "com.jadyer.annotation.UserManagerImpl" /> < bean id = "securityHandler" class = "com.jadyer.annotation.SecurityHandler" /> </ beans > |
然后是服務層接口以及實現類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
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是服務層的接口 * 下面的UserManagerImpl是服務層接口的實現類 */ 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------" ); } } |
接下來是使用AspectJ注解標注的切入類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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(),此方法沒有返回值和參數 * @see 該方法就是一個標識,不進行調用 */ @Pointcut ( "execution(* add*(..))" ) //匹配所有以add開頭的方法 private void addAddMethod(){}; /** * 定義Advice * @see 表示我們的Advice應用到哪些Pointcut訂閱的Joinpoint上 */ //@Before("addAddMethod()") @After ( "addAddMethod()" ) private void checkSecurity() { System.out.println( "------【checkSecurity is invoked】------" ); } } |
最后是客戶端測試類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package com.jadyer.annotation; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Spring對AOP的支持:采用Annotation方式 * @see ------------------------------------------------------------------------------------- * @see Spring提供的AOP功能還是很強大的,支持可配置,它的默認實現使用的就是JDK動態代理 * @see 使用Spring的AOP不需要繼承相關的東西,也不需要實現接口 * @see 但有個前提條件:由于是JDK動態代理,所以若想生成代理,該類就必須得實現一個接口才行 * @see 如果該類沒有implements接口的話,仍去使用Spring的默認AOP實現時,那么就會出錯 * @see 通常需要生成代理的類都是服務層的類,所以通常都會抽一個接口出來。即養成面向接口編程的習慣 * @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、將橫切性關注點模塊化,建立SecurityHandler.java * @see 3、采用注解指定SecurityHandler為Aspect * @see 4、采用注解定義Advice和Pointcut * @see 5、啟用AspectJ對Annotation的支持,并且將目標類和Aspect類配置到IoC容器中 * @see 6、開發客戶端 * @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配置文件實現AOP的Java Project
首先是位于src根目錄中的applicationContext-cglib.xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<? 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"> <!-- 強制使用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開頭的所有的方法 execution(* add*(..)) 匹配com.jadyer.servcices.impl包下的所有的類的所有的方法 execution(* com.jadyer.servcices.impl.*.*(..)) 匹配com.jadyer.servcices.impl包下的add或者del開頭的所有的方法 execution(* com.jadyer.servcices.impl.*.add*(..)) || execution(* com.jadyer.servcices.impl.*.del*(..)) --> |
然后是服務層接口以及實現類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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是服務層接口 * 下面的UserManagerImpl是服務層接口的實現類 */ 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中所指定的切入類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package com.jadyer.cglib; import org.aspectj.lang.JoinPoint; /** * 將客戶調用信息傳遞到該Advice中 * @see 可以在Advice中添加一個JoinPoint參數,取得客戶端調用的方法名稱及參數值 * @see 以后純粹使用AOP去寫類似這樣東西的情況比較少,我們主要使用Spring提供的事務 * @see 關于這個,知道即可。下面是示例代碼 */ public class SecurityHandler { private void checkSecurity(JoinPoint joinPoint) { for ( int i= 0 ; i<joinPoint.getArgs().length; i++) { System.out.println(joinPoint.getArgs()[i]); //獲取客戶端調用的方法的參數值 } System.out.println(joinPoint.getSignature().getName()); //獲取客戶端調用的方法名稱 System.out.println( "------【checkSecurity is invoked】------" ); } } |
最后是客戶端測試類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package com.jadyer.cglib; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @see -------------------------------------------------------------------------------------------------- * @see JDK動態代理和CGLIB代理的差別 * @see 1..JDK動態代理對實現了接口的類進行代理 * @see 2..CGLIB代理可以對類代理,主要對指定的類生成一個子類。由于是繼承,所以目標類最好不要使用final聲明 * @see -------------------------------------------------------------------------------------------------- * @see 代理方式的選擇 * @see 1..如果目標對象實現了接口,默認情況下會采用JDK動態代理實現AOP,亦可強制使用CGLIB生成代理實現AOP * @see 2..如果目標對象未實現接口,那么必須引入CGLIB,這時Spring會在JDK動態代理和CGLIB代理之間自動切換 * @see 3..比較鼓勵業務對象是針對接口編程的,所以鼓勵使用JDK動態代理。因為我們所代理的目標,一般都是業務對象 * @see -------------------------------------------------------------------------------------------------- * @see 使用CGLIG代理的步驟 * @see 1..新增CGLIB庫:SPRING_HOME//lib//cglib//*.jar * @see 2..新增配置標簽,強制使用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" ); //當UserManagerImpl實現了UserManager接口的情況下,這時Spring會自動使用JDK動態代理 //如果項目已經引入cglib庫,并在配置文件中強制使用CGLIB代理,此時Spring才會使用CGLIB代理 //UserManager userManager = (UserManager)factory.getBean("userManager"); //由于此時的UserManagerImpl并沒有實現UserManager接口,所以接收類型就不能再使用UserManager接口 //并且項目中已經引入了cglib庫,盡管配置文件中沒有強制使用CGLIB代理,但Spring會自動使用CGLIB代理 UserManagerImpl userManager = (UserManagerImpl)factory.getBean( "userManager" ); userManager.addUser( "吳三省" , "02200059" ); } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。