AOP的作用這里就不再作說明了,下面開始講解一個很簡單的入門級例子。
引用一個猴子偷桃,守護者守護果園抓住猴子的小情節。
1、猴子偷桃類(普通類):
- package com.samter.common;
- /**
- * 猴子
- * @author Administrator
- *
- */
- public class Monkey {
- public void stealPeaches(String name){
- System.out.println("【猴子】"+name+"正在偷桃...");
- }
- }
2、守護者類(聲明為Aspect):
- package com.samter.aspect;
- import org.aspectj.lang.annotation.AfterReturning;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- /**
- * 桃園守護者
- * @author Administrator
- *
- */
- @Aspect
- public class Guardian {
- @Pointcut("execution(* com.samter.common.Monkey.stealPeaches(..))")
- public void foundMonkey(){}
- @Before(value="foundMonkey()")
- public void foundBefore(){
- System.out.println("【守護者】發現猴子正在進入果園...");
- }
- @AfterReturning("foundMonkey() && args(name,..)")
- public void foundAfter(String name){
- System.out.println("【守護者】抓住了猴子,守護者審問出了猴子的名字叫“"+name+"”...");
- }
- }
3、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-2.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
- >
- <!-- 定義Aspect -->
- <bean id="guardian" class="com.samter.aspect.Guardian" />
- <!-- 定義Common -->
- <bean id="monkey" class="com.samter.common.Monkey" />
- <!-- 啟動AspectJ支持 -->
- <aop:aspectj-autoproxy />
- </beans>
4、測試類:
- package com.samter.common;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Main {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
- Monkey monkey = (Monkey) context.getBean("monkey");
- try {
- monkey.stealPeaches("孫大聖的大徒弟");
- }
- catch(Exception e) {}
- }
- }
5、控制台輸出:
- 【守護者】發現猴子正在進入果園...
- 【猴子】孫大聖的大徒弟正在偷桃...
- 【守護者】抓住了猴子,守護者審問出了猴子的名字叫“孫大聖的大徒弟”...
解說:1寫了一個猴子正在偷桃的方法。
2寫了一個標志為@Aspect的類,它是守護者。它會在猴子偷桃之前發現猴子,並在猴子偷桃之后抓住猴子。
原理:A、@Aspect的聲明表示這是一個切面類。
B、@Pointcut使用這個方法可以將com.samter.common.Monkey.stealPeaches(..)方法聲明為poincut即切入點。作用,在stealPeaches方法被調用的時候執行2的foundMonkey方法。其中execution是匹配方法執行的切入點,也就是spring最常用的切入點定義方式。
C、@Before(value="foundMonkey()"):@Before聲明為在切入點方法執行之前執行,而后面沒有直接聲明切入點,而是value="foundMonkey()",是因為如果@afterReturning等都有所改動的時候都必須全部改動,所以統一用Pointcut的foundMonkey代替,這樣子有改動的時候僅需改動一個地方。其他@AfterReturning類同。
3是xml配置文件,里面有具體的注釋。
特別說明:Guardian類里面的@Pointcut("execution(* com.samter.common.Monkey.stealPeaches(..))"),如果stealPeaches有參數則..表示所有參數,@AfterReturning("foundMonkey() && args(name,..)")的&& args(name,..)可以獲取切入點方法stealPeaches的參數。
總結:這里列舉了一個簡單的例子,但是不難引申到應用中,當你寫一個登陸系統的時候,你或許要記錄誰成功登陸了系統,誰登陸系統密碼錯誤等等的信息,這樣子你用切面是再合適不過的了,總之當你的事務邏輯都設計到日志、安全檢查、事務管理等等共同的內容的時候,用切面是要比你沒有一個事務邏輯類都有相關代碼或者相關引用好得多。
2011-08-04補充:
今天給筒子們上課,補充了一點。就是@Pointcut切入點的時候,我們改寫一下正則表達式,修改為“@Pointcut("execution(* steal*(..))")”,意思就是說,針對工程下面所有的類以steal開頭的方法都監控。即:我再添加一個大象類,它去偷香蕉(stealBanana)也會被抓。但是猴子類再加一個lookPeaches方法(看桃子)的話,就不會被抓。
源:http://samter.iteye.com/blog/410618