# 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
Spring除了支持Schema方式配置AOP,還支持注解方式:使用@AspectJ風格的切面聲明。
### 6.4.1? 啟用對@AspectJ的支持
Spring默認不支持@AspectJ風格的切面聲明,為了支持需要使用如下配置:
```
<aop:aspectj-autoproxy/>
```
這樣Spring就能發現@AspectJ風格的切面并且將切面應用到目標對象。
### 6.4.2? 聲明切面
@AspectJ風格的聲明切面非常簡單,使用@Aspect注解進行聲明:
```
@Aspect()
Public class Aspect{
……
}
```
然后將該切面在配置文件中聲明為Bean后,Spring就能自動識別并進行AOP方面的配置:
```
<bean id="aspect" class="……Aspect"/>
```
該切面就是一個POJO,可以在該切面中進行切入點及通知定義,接著往下看吧。
### 6.4.3? 聲明切入點
@AspectJ風格的命名切入點使用org.aspectj.lang.annotation包下的@Pointcut+方法(方法必須是返回void類型)實現。
```
@Pointcut(value="切入點表達式", argNames = "參數名列表")
public void pointcutName(……) {}
```
**value:**指定切入點表達式;
**argNames:**指定命名切入點方法參數列表參數名字,可以有多個用“,”分隔,這些參數將傳遞給通知方法同名的參數,同時比如切入點表達式“args(param)”將匹配參數類型為命名切入點方法同名參數指定的參數類型。
**pointcutName:**切入點名字,可以使用該名字進行引用該切入點表達式。
```
@Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {}
```
定義了一個切入點,名字為“beforePointcut”,該切入點將匹配目標方法的第一個參數類型為通知方法實現中參數名為“param”的參數類型。
### 6.4.4? 聲明通知
@AspectJ風格的聲明通知也支持5種通知類型:
**一、前置通知:**使用org.aspectj.lang.annotation 包下的@Before注解聲明;
```
@Before(value = "切入點表達式或命名切入點", argNames = "參數列表參數名")
```
**value:**指定切入點表達式或命名切入點;
**argNames:**與Schema方式配置中的同義。
接下來示例一下吧:
1、定義接口和實現,在此我們就使用Schema風格時的定義;
2、定義切面:
```
package cn.javass.spring.chapter6.aop;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class HelloWorldAspect2 {
}
```
3、定義切入點:
```
@Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {}
```
4、定義通知:
```
@Before(value = "beforePointcut(param)", argNames = "param")
public void beforeAdvice(String param) {
System.out.println("===========before advice param:" + param);
}
```
5、在chapter6/advice2.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/>
<bean id="helloWorldService"
class="cn.javass.spring.chapter6.service.impl.HelloWorldService"/>
<bean id="aspect"
class="cn.javass.spring.chapter6.aop.HelloWorldAspect2"/>
</beans>
```
6、測試代碼cn.javass.spring.chapter6.AopTest:
```
@Test
public void testAnnotationBeforeAdvice() {
System.out.println("======================================");
ApplicationContext ctx = new ClassPathXmlApplicationContext("chapter6/advice2.xml");
IHelloWorldService helloworldService = ctx.getBean("helloWorldService", IHelloWorldService.class);
helloworldService.sayBefore("before");
System.out.println("======================================");
}
```
將輸出:
```
==========================================
===========before advice param:before
============say before
==========================================
```
切面、切入點、通知全部使用注解完成:
1)使用@Aspect將POJO聲明為切面;
2)使用@Pointcut進行命名切入點聲明,同時指定目標方法第一個參數類型必須是java.lang.String,對于其他匹配的方法但參數類型不一致的將也是不匹配的,通過argNames = "param"指定了將把該匹配的目標方法參數傳遞給通知同名的參數上;
3)使用@Before進行前置通知聲明,其中value用于定義切入點表達式或引用命名切入點;
4)配置文件需要使用<aop:aspectj-autoproxy/>來開啟注解風格的@AspectJ支持;
5)需要將切面注冊為Bean,如“aspect”Bean;
6)測試代碼完全一樣。
**二、后置返回通知:**使用org.aspectj.lang.annotation 包下的@AfterReturning注解聲明;
```
@AfterReturning(
value="切入點表達式或命名切入點",
pointcut="切入點表達式或命名切入點",
argNames="參數列表參數名",
returning="返回值對應參數名")
```
**value:**指定切入點表達式或命名切入點;
**pointcut:**同樣是指定切入點表達式或命名切入點,如果指定了將覆蓋value屬性指定的,pointcut具有高優先級;
**argNames:**與Schema方式配置中的同義;
**returning:**與Schema方式配置中的同義。
```
@AfterReturning(
value="execution(* cn.javass..*.sayBefore(..))",
pointcut="execution(* cn.javass..*.sayAfterReturning(..))",
argNames="retVal", returning="retVal")
public void afterReturningAdvice(Object retVal) {
System.out.println("===========after returning advice retVal:" + retVal);
}
```
其中測試代碼與Schema方式幾乎一樣,在此就不演示了,如果需要請參考AopTest.java中的testAnnotationAfterReturningAdvice測試方法。
**三、后置異常通知:**使用org.aspectj.lang.annotation 包下的@AfterThrowing注解聲明;
```
@AfterThrowing (
value="切入點表達式或命名切入點",
pointcut="切入點表達式或命名切入點",
argNames="參數列表參數名",
throwing="異常對應參數名")
```
**value:**指定切入點表達式或命名切入點;
**pointcut:**同樣是指定切入點表達式或命名切入點,如果指定了將覆蓋value屬性指定的,pointcut具有高優先級;
**argNames:**與Schema方式配置中的同義;
**throwing:**與Schema方式配置中的同義。
```
@AfterThrowing(
value="execution(* cn.javass..*.sayAfterThrowing(..))",
argNames="exception", throwing="exception")
public void afterThrowingAdvice(Exception exception) {
System.out.println("===========after throwing advice exception:" + exception);
}
```
其中測試代碼與Schema方式幾乎一樣,在此就不演示了,如果需要請參考AopTest.java中的testAnnotationAfterThrowingAdvice測試方法。
**四、后置最終通知:**使用org.aspectj.lang.annotation 包下的@After注解聲明;
```
@After (
value="切入點表達式或命名切入點",
argNames="參數列表參數名")
```
**value:**指定切入點表達式或命名切入點;
**argNames:**與Schema方式配置中的同義;
```
@After(value="execution(* cn.javass..*.sayAfterFinally(..))")
public void afterFinallyAdvice() {
System.out.println("===========after finally advice");
}
```
其中測試代碼與Schema方式幾乎一樣,在此就不演示了,如果需要請參考AopTest.java中的testAnnotationAfterFinallyAdvice測試方法。
**五、環繞通知:**使用org.aspectj.lang.annotation 包下的@Around注解聲明;
```
@Around (
value="切入點表達式或命名切入點",
argNames="參數列表參數名")
```
**value:**指定切入點表達式或命名切入點;
**argNames:**與Schema方式配置中的同義;
```
@Around(value="execution(* cn.javass..*.sayAround(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("===========around before advice");
Object retVal = pjp.proceed(new Object[] {"replace"});
System.out.println("===========around after advice");
return retVal;
}
```
其中測試代碼與Schema方式幾乎一樣,在此就不演示了,如果需要請參考AopTest.java中的annotationAroundAdviceTest測試方法。
### 6.4.5? 引入
@AspectJ風格的引入聲明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents聲明:
```
@DeclareParents(
value=" AspectJ語法類型表達式",
defaultImpl=引入接口的默認實現類)
private Interface interface;
```
**value:**匹配需要引入接口的目標對象的AspectJ語法類型表達式;與Schema方式中的types-matching屬性同義;
private Interface interface**:**指定需要引入的接口;
defaultImpl**:**指定引入接口的默認實現類,沒有與Schema方式中的delegate-ref屬性同義的定義方式;
```
@DeclareParents(
value="cn.javass..*.IHelloWorldService+", defaultImpl=cn.javass.spring.chapter6.service.impl.IntroductiondService.class)
private IIntroductionService introductionService;
```
其中測試代碼與Schema方式幾乎一樣,在此就不演示了,如果需要請參考AopTest.java中的testAnnotationIntroduction測試方法。
原創內容,轉載請注明出處【[http://sishuok.com/forum/blogPost/list/0/2471.html](http://sishuok.com/forum/blogPost/list/0/2471.html#7143)】
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC