AOP作為Spring這個輕量級的容器中很重要的一部分,得到越來越多的關注,Spring的Transaction就是用AOP來管理的,今天就通過簡單的例子來看看Spring中的AOP的基本使用方法。

? 首先確定將要Proxy的目標,在Spring中默認采用JDK中的dynamic proxy,它只能夠實現接口的代理,如果想對類進行代理的話,需要采用CGLIB的proxy。顯然,選擇“編程到接口”是更明智的做法,下面是將要代理的接口:

?

?public?interface?FooInterface?{
????
public?void?printFoo();
????
public?void?dummyFoo();
??}

??
? 以及其一個簡單的實現:
??
??

public?class?FooImpl?implements?FooInterface?{
????
public?void?printFoo()?{
??????System.out.println(
"In?FooImpl.printFoo");
????}

????
public?void?dummyFoo()?{
??????System.out.println(
"In?FooImpl.dummyFoo");
????}

??}

??
? 接下來創建一個Advice,在Spring中支持Around,Before,After returning和Throws四種Advice,這里就以簡單的Before Advice舉例:
??
?

?public?class?PrintBeforeAdvice?implements?MethodBeforeAdvice?{
????
public?void?before(Method?arg0,?Object[]?arg1,?Object?arg2)?throws?Throwable?{
??????System.out.println(
"In?PrintBeforeAdvice");
????}

??}

??
? 有了自己的business interface和advice,剩下的就是如何去裝配它們了,首先利用ProxyFactory以編程方式實現,如下:
??
?

?public?class?AopTestMain?{
????
public?static?void?main(String[]?args)?{
??????FooImpl?fooImpl?
=?new?FooImpl();
??????PrintBeforeAdvice?myAdvice?
=?new?PrintBeforeAdvice();
??????
??????ProxyFactory?factory?
=?new?ProxyFactory(fooImpl);
??????factory.addBeforeAdvice(myAdvice);
??????FooInterface?myInterface?
=?(FooInterface)factory.getProxy();

??????myInterface.printFoo();
??????myInterface.dummyFoo();
????}

??}


??
? 現在執行程序,神奇的結果就出現了:
?
? In PrintBeforeAdvice
? In FooImpl.printFoo
? In PrintBeforeAdvice
? In FooImpl.dummyFoo

?
? 雖然這樣能體會到Spring中AOP的用法,但這決不是值得推薦的方法,既然使用了Spring,在ApplicationContext中裝配所需要 的bean才是最佳策略,實現上面的功能只需要寫個簡單的applicationContext就可以了,如下:
?

??<?xml?version="1.0"?encoding="UTF-8"?>
??
<!DOCTYPE?beans?PUBLIC?"-//SPRING//DTD?BEAN//EN"?
????
"http://www.springframework.org/dtd/spring-beans.dtd">

??
<beans>
????
<description>The?aop?application?context</description>
????
<bean?id="fooTarget"?class="FooImpl"/>
????
<bean?id="myAdvice"?class="PrintBeforeAdvice"/>
????
<bean?id="foo"?class="org.springframework.aop.framework.ProxyFactoryBean">
?????
<property?name="proxyInterfaces">
???????
<value>FooInterface</value>
?????
</property>
?????
<property?name="target">
???????
<ref?local="fooTarget"/>
?????
</property>
?????
<property?name="interceptorNames">
???????
<list>
?????????
<value>myAdvice</value>
???????
</list>
?????
</property>
????
</bean>
??
</beans>

??

當然,main中的代碼也要進行相應的修改:
?????
?

?public?static?void?main(String[]?args)?{
????ClassPathXmlApplicationContext?context?
=?new?
?????????????ClassPathXmlApplicationContext(
"applicationContext.xml");
????FooInterface?foo?
=?(FooInterface)context.getBean("foo");
????foo.printFoo();
????foo.dummyFoo();
??}

??
? 現在運行一下,結果將和上面的運行結果完全一樣,這樣是不是更優雅?當需要更改實現時,只需要修改配置文件就可以了,程序中的代碼不需任何改動。
?
? 但是,這時候會發現被proxy的object中的所有方法調用時都將運行advice中的before,這顯然不能滿足絕大多數情況下的需要,此時,只 需借用Advisor就可以了,當然要在Advisor中利用pattern設置好哪些方法需要advice,更改applicationContext 如下:
??
??

<?xml?version="1.0"?encoding="UTF-8"?>
??
<!DOCTYPE?beans?PUBLIC?"-//SPRING//DTD?BEAN//EN"?
????
"http://www.springframework.org/dtd/spring-beans.dtd">

??
<beans>
????
<description>The?springeva?application?context</description>
????
<bean?id="fooTarget"?class="FooImpl"/>
????
<bean?id="printBeforeAdvice"?class="PrintBeforeAdvice"/>
????
<bean?id="myAdvisor"?
??????????
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

??????
<property?name="advice">
????????
<ref?local="printBeforeAdvice"/>
??????
</property>
??????
<property?name="pattern">
????????
<value>.*print.*</value>
??????
</property>
????
</bean>
????
<bean?id="foo"?class="org.springframework.aop.framework.ProxyFactoryBean">
??????
<property?name="proxyInterfaces">
????????
<value>FooInterface</value>
??????
</property>
??????
<property?name="target">
????????
<ref?local="fooTarget"/>
??????
</property>
??????
<property?name="interceptorNames">
????????
<list>
??????????
<value>myAdvisor</value>
????????
</list>
??????
</property>
????
</bean>
??
</beans>

? 主程序不需進行任何修改,運行結果已經變樣了:

? In PrintBeforeAdvice
? In FooImpl.printFoo
? In FooImpl.dummyFoo

?
? 至此,應該已經理解了Spring中AOP的使用方法,當然Spring中AOP最重要的應用是Transaction Manager