使用注解定義切面


 1 /**
 2  * 使用注解定義切面
 3  */
 4 @Aspect
 5 public class UserServiceLogger {
 6     private static final Logger log = Logger.getLogger(UserServiceLogger.class);
 7     
 8     @Pointcut("execution(* service.UserService.*(..))")
 9     public void pointcut() {}
10 
11     @Before("pointcut()")
12     public void before(JoinPoint jp) {
13         log.info("調用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
14                 + " 方法。方法入參:" + Arrays.toString(jp.getArgs()));
15     }
16 
17     @AfterReturning(pointcut = "pointcut()", returning = "returnValue")
18     public void afterReturning(JoinPoint jp, Object returnValue) {
19         log.info("調用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
20                 + " 方法。方法返回值:" + returnValue);
21     }
22 
23 }

@Aspect注解將UserServiceLogger定義為切面,並且使用@Before注解將before()方法定義為前置增強,使用@AfterReturning注解將afterReturning()方法定義為后置增強。為了能夠獲得當前連接點的信息,在增強方法中添加了JoinPoint類型的參數,Spring會自動注入該實例。切入點表達式使用@Pointcut注解來表示,而切入點則需要通過一個普通的方法定義來提供,作為切入點的方法必須返回void類型。

切面定義完后,還需要在Spring配置文件中完成織入工作。

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:context="http://www.springframework.org/schema/context"
 5     xmlns:aop="http://www.springframework.org/schema/aop"
 6     xsi:schemaLocation="http://www.springframework.org/schema/beans
 7     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 8     http://www.springframework.org/schema/context
 9     http://www.springframework.org/schema/context/spring-context-3.2.xsd
10     http://www.springframework.org/schema/aop
11     http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
12 
13     <context:component-scan base-package="service,dao" />
14     <bean class="aop.UserServiceLogger"></bean>
15     <aop:aspectj-autoproxy />
16 </beans>

配置文件中受限要導入aop的命名空間。只需在配置文件中添加<aop:aspectj-autoproxy/>元素,就可以啟用對於@AspectJ注解的支持,Spring將自動為匹配的Bean創建代理。

為了注冊定義好的切面,還要在配置文件中聲明UserServiceLogger的一個實例。如果不需要被其他Bean引用,可以不指定id屬性。

 1 /**
 2  * 通過注解實現異常拋出增強
 3  */
 4 @Aspect
 5 public class ErrorLogger {
 6     private static final Logger log = Logger.getLogger(ErrorLogger.class);
 7 
 8     @AfterThrowing(pointcut = "execution(* service.UserService.*(..))", throwing = "e")
 9     public void afterThrowing(JoinPoint jp, RuntimeException e) {
10         log.error(jp.getSignature().getName() + " 方法發生異常:" + e);
11     }
12 
13 }

使用@AfterThrowing注解可以定義異常拋出增強。如果需要獲取拋出的異常,可以為增強方法聲明相關類型的參數,並通過@AfterThrowing注解的throwing屬性指定該參數名稱,Spring會為其注入從目標方法拋出的異常實例。

 1 /**
 2  * 通過注解實現最終增強
 3  */
 4 @Aspect
 5 public class AfterLogger {
 6     private static final Logger log = Logger.getLogger(AfterLogger.class);
 7 
 8     @After("execution(* service.UserService.*(..))")
 9     public void afterLogger(JoinPoint jp) {
10         log.info(jp.getSignature().getName() + " 方法結束執行。");
11     }
12 
13 }

@After注解可以定義最終增強。

 1 /**
 2  * 通過注解實現環繞增強
 3  */
 4 @Aspect
 5 public class AroundLogger {
 6     private static final Logger log = Logger.getLogger(AroundLogger.class);
 7 
 8     @Around("execution(* service.UserService.*(..))")
 9     public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable {
10         log.info("調用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
11                 + " 方法。方法入參:" + Arrays.toString(jp.getArgs()));
12         try {
13             Object result = jp.proceed();
14             log.info("調用 " + jp.getTarget() + " 的 "
15                     + jp.getSignature().getName() + " 方法。方法返回值:" + result);
16             return result;
17         } catch (Throwable e) {
18             log.error(jp.getSignature().getName() + " 方法發生異常:" + e);
19             throw e;
20         } finally {
21             log.info(jp.getSignature().getName() + " 方法結束執行。");
22         }
23     }
24 
25 }

@Around注解可以定義環繞增強。通過為增強方法聲明ProceedingJoinPoint類型的參數,可以獲得連接點信息。通過它的proceed()方法可以調用真正的目標方法,從而實現對連接點的完全控制。


免責聲明!

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



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