(一)spring aop的兩種配置方式。


  sring aop的方式有兩種:(1)xml文件配置方式(2)注解的方式實現,我們可以先通過一個demo認識spring aop的實現,然后再對其進行詳細的解釋。

一、基於注解的springAop配置。

   環境准備階段:

   (1)pom.xml:

 1 <dependencies>
 2         <!-- 引入Spring-AOP等相關Jar -->
 3         <dependency>
 4             <groupId>org.springframework</groupId>
 5             <artifactId>spring-core</artifactId>
 6             <version>3.0.6.RELEASE</version>
 7         </dependency>
 8         <dependency>
 9             <groupId>org.springframework</groupId>
10             <artifactId>spring-context</artifactId>
11             <version>3.0.6.RELEASE</version>
12         </dependency>
13         <dependency>
14             <groupId>org.springframework</groupId>
15             <artifactId>spring-aop</artifactId>
16             <version>3.0.6.RELEASE</version>
17         </dependency>
18         <dependency>
19             <groupId>org.springframework</groupId>
20             <artifactId>spring-orm</artifactId>
21             <version>3.0.6.RELEASE</version>
22         </dependency>
23         <dependency>
24             <groupId>org.aspectj</groupId>
25             <artifactId>aspectjrt</artifactId>
26             <version>1.6.1</version>
27         </dependency>
28         <dependency>
29             <groupId>aspectj</groupId>
30             <artifactId>aspectjweaver</artifactId>
31             <version>1.5.3</version>
32         </dependency>
33         <dependency>
34             <groupId>cglib</groupId>
35             <artifactId>cglib</artifactId>
36             <version>2.1_2</version>
37         </dependency>
38 
39         <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
40         <dependency>
41             <groupId>com.mchange</groupId>
42             <artifactId>c3p0</artifactId>
43             <version>0.9.5.2</version>
44         </dependency>
45         <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
46         <dependency>
47             <groupId>mysql</groupId>
48             <artifactId>mysql-connector-java</artifactId>
49             <version>5.1.37</version>
50         </dependency>
51 
52         <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
53         <dependency>
54             <groupId>dom4j</groupId>
55             <artifactId>dom4j</artifactId>
56             <version>1.6.1</version>
57         </dependency>
58         <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
59         <dependency>
60             <groupId>commons-lang</groupId>
61             <artifactId>commons-lang</artifactId>
62             <version>2.6</version>
63         </dependency>
64     </dependencies>

 (2)定義接口:

 1 package cn.spring.aop.dao;
 2 
 3 /**
 4  * @author Simple
 5  * @date 10:01 2019/8/20
 6  * @description
 7  */
 8 public interface UserService {
 9     public void save();
10 }

 (3)接口實現類:

 1 package cn.spring.aop.dao;
 2 
 3 import org.springframework.stereotype.Service;
 4 
 5 /**
 6  * @author Simple
 7  * @date 9:57 2019/8/20
 8  * @description
 9  */
10 @Service
11 public class UserServiceImpl implements UserService {
12 
13     @Override
14     public void save() {
15         System.out.println("保存成功.....");
16     }
17 }

 (4)Aop類: 

 1 package cn.spring.aop;
 2 
 3 import org.aspectj.lang.ProceedingJoinPoint;
 4 import org.aspectj.lang.annotation.*;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * @author Simple
 9  * @date 10:06 2019/8/20
10  * @description
11  */
12 @Component
13 @Aspect
14 public class AopAspect {
15     /**
16      * 前置通知
17      */
18     @Before("execution(* cn.spring.aop.dao.UserService.save(..))")
19     public void before(){
20         System.out.println("前置通知....");
21     }
22 
23     /**
24      * 后置通知
25      * returnVal,切點方法執行后的返回值
26      */
27     @AfterReturning(value="execution(* cn.spring.aop.dao.UserService.save(..))",returning = "returnVal")
28     public void AfterReturning(Object returnVal){
29         System.out.println("后置通知...."+returnVal);
30     }
31 
32 
33     /**
34      * 環繞通知
35      * @param joinPoint 可用於執行切點的類
36      * @return
37      * @throws Throwable
38      */
39     @Around("execution(* cn.spring.aop.dao.UserService.save(..))")
40     public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
41         System.out.println("環繞通知前....");
42         Object obj= (Object) joinPoint.proceed();
43         System.out.println("環繞通知后....");
44         return obj;
45     }
46 
47     /**
48      * 拋出通知
49      * @param e
50      */
51     @AfterThrowing(value="execution(* cn.spring.aop.dao.UserService.save(..))",throwing = "e")
52     public void afterThrowable(Throwable e){
53         System.out.println("出現異常:msg="+e.getMessage());
54     }
55 
56     /**
57      * 無論什么情況下都會執行的方法
58      */
59     @After(value="execution(* cn.spring.aop.dao.UserService.save(..))")
60     public void after(){
61         System.out.println("最終通知....");
62     }
63 }

 (5)spring.xml

 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:aop="http://www.springframework.org/schema/aop"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 6         http://www.springframework.org/schema/aop
 7         http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 8     <!-- 開啟注解掃描 -->
 9       <context:component-scan base-package="cn.spring.aop"></context:component-scan>
10     <!-- 啟動@aspectj的自動代理支持-->
11       <aop:aspectj-autoproxy />
12 </beans>

 (6)測試類:

 1 package cn.spring.aop;
 2 
 3 import cn.spring.aop.dao.UserService;
 4 import cn.spring.aop.dao.UserServiceImpl;
 5 import org.springframework.context.ApplicationContext;
 6 import org.springframework.context.support.ClassPathXmlApplicationContext;
 7 
 8 /**
 9  * @author Simple
10  * @date 10:13 2019/8/20
11  * @description
12  */
13 public class TestDemo {
14     public static void main(String[] args) {
15         ApplicationContext ac =new ClassPathXmlApplicationContext("spring.xml");
16         UserService userService = (UserService) ac.getBean("userServiceImpl");
17         userService.save();
18     }
19 }

 (7)運行結果:

二、配置詳解

(1)spring.xml中注解的作用

1.spring--<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 

   這個是 開啟事物注解權限,引入了三個jar包  aspectjweaver.jar aspectjrt.jar aspectj.jar  aopalliance.jar。

   2.Spring -- <context:component-scan>

   在xml配置了這個標簽后,spring可以自動去掃描base-pack下面或者子包下面的java文件,如果掃描到有@Component @Controller@Service等這些注解的類,則把這些類注冊為bean。

(2)Aop類中的注解

         在aop類中,編寫了5種注解類型的通知函數:

   @Before 前置通知

   @AfterReturning 后置通知

   @Around 環繞通知

   @AfterThrowing 異常通知

   @After 最終通知

   @pointcut 定義切點匹配表達式

(3)切點表達式

  1. execution

   由於Spring切面粒度最小是達到方法級別,而execution表達式可以用於明確指定方法返回類型,類名,方法名和參數名等與方法相關的部件,並且在Spring中,大部分需要使用AOP的業務場景也只需要達到方法級別即可,因而execution表達式的使用是最為廣泛的。如下是execution表達式的語法:

 execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

 這里問號表示當前項可以有也可以沒有,其中各項的語義如下:
  • modifiers-pattern方法的可見性,如public,protected;
  • ret-type-pattern:方法的返回值類型,如int,void等;
  • declaring-type-pattern:方法所在類的全路徑名,如com.spring.Aspect;
  • name-pattern:方法名類型,如buisinessService();
  • param-pattern:方法的參數類型,如java.lang.String;
  • throws-pattern:方法拋出的異常類型,如java.lang.Exception;

       如下是一個使用execution表達式的例子:

 execution(public * com.spring.service.BusinessObject.businessService(java.lang.String,..))

      上述切點表達式將會匹配使用public修飾,返回值為任意類型,並且是com.spring.BusinessObject類中名稱為businessService的方法,方法可以有多個參數,但是第一個參數必須是java.lang.String類型的方法。         

   通配符的類型,主要有兩種:

  • *通配符,該通配符主要用於匹配單個單詞,或者是以某個詞為前綴或后綴的單詞。

           如下示例表示返回值為任意類型,在com.spring.service.BusinessObject類中,並且參數個數為零的方法:execution(* com.spring.service.BusinessObject.*())

  • ..通配符,該通配符表示0個或多個項,主要用於declaring-type-pattern和param-pattern中,如果用於declaring-type-pattern中,則表示匹配當前包及其子包,如果用於param-pattern中,則表示匹配0個或多個參數。

如下示例表示匹配返回值為任意類型,並且是com.spring.service包及其子包下的任意類的名稱為businessService的方法,而且該方法不能有任何參數:execution(* com.spring.service..*.businessService())

這里需要說明的是,包路徑service..*.businessService()中的..應該理解為延續前面的service路徑,表示到service路徑為止,或者繼續延續service路徑,從而包括其子包路徑;后面的*.businessService(),這里的*表示匹配一個單詞,因為是在方法名前,因而表示匹配任意的類。

 如下示例是使用..表示任意個數的參數的示例,需要注意,表示參數的時候可以在括號中事先指定某些類型的參數,而其余的參數則由..進行匹配:

execution(* com.spring.service.BusinessObject.businessService(java.lang.String,..))

三、基於xml的SpringAop配置

  xml配置主要是將注解轉換為xml這里我們在上述的情況下做下修改,主要修改兩個地方:1,spring.xml,2 aop類

1.springaop.xml

 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:aop="http://www.springframework.org/schema/aop"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 6         http://www.springframework.org/schema/aop
 7         http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 8     <!--基於配置需要我們手動進行配置-->
 9     <!-- dao 實例 -->
10     <bean id="userService" class="cn.spring.aop.dao.UserServiceImpl"></bean>
11     <!-- 切面類 -->
12     <bean id="aop" class="cn.spring.aop.AopAspect2"></bean>
13     <!-- Aop配置 -->
14     <aop:config>
15         <!-- 定義一個切入點表達式: 攔截哪些方法 -->
16         <aop:pointcut expression="execution(* cn.spring.aop.dao.UserService.*(..))"  id="pt"/>
17         <!-- 切面 -->
18         <aop:aspect ref="aop">
19             <!-- 環繞通知 -->
20             <aop:around method="around" pointcut-ref="pt"/>
21             <!-- 前置通知: 在目標方法調用前執行 -->
22             <aop:before method="before" pointcut-ref="pt"/>
23             <!-- 后置通知: -->
24             <aop:after method="after" pointcut-ref="pt"/>
25             <!-- 返回后通知 -->
26             <aop:after-returning method="afterReturning" pointcut-ref="pt" />
27             <!-- 異常通知 -->
28             <aop:after-throwing method="after" pointcut-ref="pt"/>
29         </aop:aspect>
30     </aop:config>
31 </beans>

 2.aop類  AopAspect2

 1 package cn.spring.aop;
 2 
 3 import org.aspectj.lang.ProceedingJoinPoint;
 4 import org.aspectj.lang.annotation.*;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * @author Simple
 9  * @date 10:06 2019/8/20
10  * @description
11  */
12 @Component
13 @Aspect
14 public class AopAspect2 {
15     /**
16      * 前置通知
17      */
18     public void before(){
19         System.out.println("前置通知....");
20     }
21 
22     /**
23      * 后置通知
24      * returnVal,切點方法執行后的返回值
25      */
26     public void afterReturning(){
27         System.out.println("后置通知....");
28     }
29 
30 
31     /**
32      * 環繞通知
33      * @param joinPoint 可用於執行切點的類
34      * @return
35      * @throws Throwable
36      */
37     public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
38         System.out.println("環繞通知前....");
39         Object obj= (Object) joinPoint.proceed();
40         System.out.println("環繞通知后....");
41         return obj;
42     }
43 
44     /**
45      * 拋出通知
46      * @param e
47      */
48     public void afterThrowable(Throwable e){
49         System.out.println("出現異常:msg="+e.getMessage());
50     }
51 
52     /**
53      * 無論什么情況下都會執行的方法
54      */
55     public void after(){
56         System.out.println("最終通知....");
57     }
58 }

 3.測試方法

 1 package cn.spring.aop;
 2 
 3 import cn.spring.aop.dao.UserService;
 4 import cn.spring.aop.dao.UserServiceImpl;
 5 import org.springframework.context.ApplicationContext;
 6 import org.springframework.context.support.ClassPathXmlApplicationContext;
 7 
 8 /**
 9  * @author Simple
10  * @date 10:13 2019/8/20
11  * @description
12  */
13 public class TestDemo {
14     public static void main(String[] args) {
15         ApplicationContext ac =new ClassPathXmlApplicationContext("springaop.xml");
16         UserService userService = (UserService) ac.getBean("userService");
17         userService.save();
18     }
19 }

 4.運行結果

     現在在開發中主要是使用注解進行開發,方便快捷,但是更多的是配置和注解一塊使用,springaop在配置方面很多都是這種注解加配置,原因主要是方便管理維護。我們這里主要講的是兩種方式的使用和切點表達式。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM