Sun River
          Topics about Java SE, Servlet/JSP, JDBC, MultiThread, UML, Design Pattern, CSS, JavaScript, Maven, JBoss, Tomcat, ...
          posts - 78,comments - 0,trackbacks - 0

          Spring 中的 AOP 簡單使用

          ???

          ??? 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 ,舉個這方面的 applicationContext 例子看看:
          ?
          ? <?xml version="1.0" encoding="UTF-8"?>
          ? <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "spring-beans.dtd">

          <beans>
          ??? <bean id="propertyConfigurer"???
          ???????? class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          ????? <property name="location">
          ??????? <value>/WEB-INF/jdbc.properties</value>
          ??????</property>
          ?? ?</bean>
          ??? <bean id="dataSource"
          ????????? class="org.springframework.jdbc.datasource.DriverManagerDataSource">
          ????? <property name="driverClassName">
          ??????? <value>${jdbc.driverClassName}</value>
          ????? </property>
          ??????<property name="url">
          ??????? <value>${jdbc.url}</value>
          ????? </property>
          ????? <property name="username">
          ??????? <value>${jdbc.username}</value>
          ????? </property>
          ????? <property name="password">
          ??????? <value>${jdbc.password}</value>
          ????? </property>
          ??? </bean>
          ?? ?<bean id="sessionFactory"
          ????????? class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
          ????? <property name="dataSource">
          ??????? <ref local="dataSource"/>
          ????? </property>
          ????? <property name="mappingResources">
          ??????? <value>smartmenu.hbm.xml</value>
          ????? </property>
          ????? <property name="hibernateProperties">
          ??????? <props>
          ????????? <prop key="hibernate.dialect">${hibernate.dialect}</prop>
          ??????? </props>
          ????? </property>
          ??? </bean>
          ?
          ??? <bean id="transactionManager"???????
          ????????? class="org.springframework.orm.hibernate.HibernateTransactionManager">
          ????? <property name="sessionFactory">
          ??????? <ref local="sessionFactory"/>
          ????? </property>
          ??? </bean>
          ??? <bean id="smartmenuTarget" class="SmartMenuHibernate">
          ????? <property name="sessionFactory">
          ??????? <ref local="sessionFactory"/>
          ????? </property>
          ??? </bean>
          ?? ?<bean id="smartMenu"
          ??????? class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          ????? <property name="transactionManager">
          ??????? <ref local="transactionManager"/>
          ????? </property>
          ????? <property name="target">
          ??????? <ref local="smartmenuTarget"/>
          ????? </property>
          ????? <property name="transactionAttributes">
          ??????? <props>
          ????????? <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
          ????????? <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
          ??????? </props>
          ????? </property>
          ??? </bean>
          ? </beans>
          ?
          ?
          要想徹底理解 Spring AOP ,最好還是多看看源碼,開源就是好啊!

          ?

          ?

          ?

          posted on 2006-11-16 13:29 Sun River 閱讀(291) 評論(0)  編輯  收藏 所屬分類: AOP
          主站蜘蛛池模板: 溧阳市| 三河市| 蒙阴县| 河南省| 南宁市| 长治市| 朝阳区| 张家界市| 奉化市| 五家渠市| 五大连池市| 仲巴县| 冕宁县| 云南省| 威海市| 驻马店市| 芜湖县| 昭苏县| 恩施市| 揭东县| 长汀县| 宁波市| 同心县| 罗定市| 伊宁市| 肇东市| 黄大仙区| 柳河县| 苍梧县| 房产| 黎城县| 太仓市| 株洲市| 梁平县| 鄯善县| 龙陵县| 麻栗坡县| 临潭县| 吐鲁番市| 威宁| 正宁县|