Spring AOP 2.0 研究

我們用Hello的例子來詮釋Spring AOP 2.0 的特性。
Hello

public interface Hello {
	void sayHelloBefore();

	void sayHelloAfter();

	void sayHelloAround();
}

SayHello

public class SayHello implements Hello{
	/**
	 * 
	 */
	public void sayHelloBefore() {
		System.out.println("say Hello before!");
	}

	/**
	 * 
	 */
	public void sayHelloAfter() {
		System.out.println("say Hello after!");
	}

	/**
	 * 
	 */
	public void sayHelloAround() {
		System.out.println("say Hello around!");
	}
}

Before

public class Before {
	public void invoke(JoinPoint joinPoint) {
		System.out.println("Before:" + joinPoint.getSignature().getName());
	}
}

After

public class After {
	public void invoke(JoinPoint joinPoint) {
	System.out.println("After:" + joinPoint.getSignature().getName());
	}
}

Around

public class Around {
	public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("Around:" + joinPoint.getSignature().getName());
		return joinPoint.proceed();
	}
}

Introduction

public class Introduction {
	public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out
				.println("Introduction:" + joinPoint.getSignature().getName());
		return joinPoint.proceed();
	}
}

Introduction 引入的作用在於是一個類在不做任何代碼修改的前提下,擁有另一套方法,或者說具備另一套本領,比如我們現在就想讓這個實現了Hello接口的SayHello類擁有Ok接口的方法

public interface Ok {
	void sayOk();
}

IntroductionOk  首先要解決上述接口Ok的實現

public class IntroductionOk implements Ok {
 
	@Override
	public void sayOk() {
		System.out.println("Ok!");
	}
}

AllTest

public class AllTest {
	private ApplicationContext app;

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		app = new ClassPathXmlApplicationContext("applicationContext.xml");
	}

	@Test
	public final void testHello() {
		Hello hello = (Hello) app.getBean("hello");
		hello.sayHelloBefore();
		hello.sayHelloAfter();
		hello.sayHelloAround();

		// 由於對Hello接口進行了引入,
		// 使得實現了Hello接口的類可以具備Ok接口的功能。
		// 同時,我們可以攔截這個方法讓他執行其他我們需要執行的操作
		hello.sayHelloIntroduction();
		((Ok) hello).sayOk();
	}

}

關於表達式符號
.*+定義目標爲包下的所有類
+定義目標爲該接口的所有實現類
<?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.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
	<bean
		id="hello"
		class="org.zlex.aop.SayHello" />
	<!-- after -->
	<bean
		id="after"
		class="org.zlex.aop.After" />
	<aop:config>
		<aop:pointcut
			id="afterPoint"
			expression="execution(* org.zlex.aop.Hello.sayHelloAfter(..))" />
		<aop:aspect
			id="afterAspect"
			ref="after">
			<aop:after
				method="invoke"
				pointcut-ref="afterPoint" />
		</aop:aspect>
	</aop:config>
	<!-- before -->
	<bean
		id="before"
		class="org.zlex.aop.Before" />
	<aop:config>
		<aop:pointcut
			id="beforePoint"
			expression="execution(* org.zlex.aop.Hello.sayHelloBefore(..))" />
		<aop:aspect
			id="beforeAspect"
			ref="before">
			<aop:before
				method="invoke"
				pointcut-ref="beforePoint" />
		</aop:aspect>
	</aop:config>
	<!-- around -->
	<bean
		id="around"
		class="org.zlex.aop.Around" />
	<aop:config>
		<aop:pointcut
			id="aroundPoint"
			expression="execution(* org.zlex.aop.Hello.sayHelloAround(..))" />
		<aop:aspect
			id="aroundAspect"
			ref="around">
			<aop:around
				method="invoke"
				pointcut-ref="aroundPoint" />
		</aop:aspect>
	</aop:config>
	<!-- introduction -->
	<!-- 
	.*+是用於包下的,不是用於接口
	+定義目標爲該接口的所有實現類
	 -->
	<bean
		id="introduction"
		class="org.zlex.aop.Introduction" />
	<bean
		id="introductionOk"
		class="org.zlex.aop.IntroductionOk" />
	<aop:config>
		<aop:aspect
			ref="introduction">
			<aop:pointcut
				id="introductionPoint"
				expression="execution(* org.zlex.aop.Hello.sayHelloIntroduction(..))" />
			<aop:declare-parents
				implement-interface="org.zlex.aop.Ok"
				types-matching="org.zlex.aop.Hello+"
				delegate-ref="introductionOk" />
			<aop:around
				method="invoke"
				pointcut-ref="introductionPoint" />
		</aop:aspect>
	</aop:config>
</beans>

執行查看日誌:
引用

Before:sayHelloBefore
say SayHello before!
say Hello after!
After:sayHelloAfter
Around:sayHelloAround
say Hello around!
Introduction:sayHelloIntroduction
say Hello introduction!
Ok!

仔細觀察
引用

Before:sayHelloBefore
say Hello before!

在輸出say Hello before!前輸出Before:sayHelloBefore
引用

say Hello after!
After:sayHelloAfter

在輸出say Hello after!後輸出After:sayHelloAfter
Around比較特殊,可以用ProceedingJoinPoint調用proceed()方法
引用

Around:sayHelloAround
say Hello around!

引用

Introduction:sayHelloIntroduction
say Hello introduction!
Ok!

同樣是Hello接口,在執行了sayHelloIntroduction方法時被攔截,同時輸出say Hello introduction!,此時還可以執行Ok的方法輸出
引用
Ok!
。顯然,Hello的實現類多了Ok接口的本領。
Spring Beans 結構圖如下:
96d51eeb-0867-3445-bafc-5c41b87fd9d3.jpg
如此這樣,就可以控制AOP了,當前資料少,實例也少,繼續研究!希望能做出來點實際的東西。
  • 96d51eeb-0867-3445-bafc-5c41b87fd9d3-thumb.jpg
  • 描述: spring beans 結構圖
  • 大小: 164.9 KB
  • aop.zip (18.5 KB)
  • 描述: 項目源代碼
  • 下載次數: 26
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章