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

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

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

           
            以及其一個簡單的實現(xiàn):
           
            public class FooImpl implements FooInterface {
              public void printFoo() {
                System.out.println("In FooImpl.printFoo");
              }
              public void dummyFoo() {
                System.out.println("In FooImpl.dummyFoo");
              }
            }

           
            接下來創(chuàng)建一個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以編程方式實現(xiàn),如下:
           
            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();
              }
            }
           
            現(xiàn)在執(zhí)行程序,神奇的結果就出現(xiàn)了:
           
            In PrintBeforeAdvice
            In FooImpl.printFoo
            In PrintBeforeAdvice
            In FooImpl.dummyFoo

           
            雖然這樣能體會到Spring中AOP的用法,但這決不是值得推薦的方法,既然使用了Spring,在ApplicationContext中裝配所需要 的bean才是最佳策略,實現(xiàn)上面的功能只需要寫個簡單的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();
            }

           
            現(xiàn)在運行一下,結果將和上面的運行結果完全一樣,這樣是不是更優(yōu)雅?當需要更改實現(xiàn)時,只需要修改配置文件就可以了,程序中的代碼不需任何改動。
           
            但是,這時候會發(fā)現(xiàn)被proxy的object中的所有方法調(diào)用時都將運行advice中的before,這顯然不能滿足絕大多數(shù)情況下的需要,此時,只 需借用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>

            主程序不需進行任何修改,運行結果已經(jīng)變樣了:

            In PrintBeforeAdvice
            In FooImpl.printFoo
            In FooImpl.dummyFoo

           
            至此,應該已經(jīng)理解了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 2005-02-04 11:15 jacky 閱讀(1610) 評論(0)  編輯  收藏 所屬分類: Open source
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(10)

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          java

          搜索

          •  

          最新評論


          主站蜘蛛池模板: 曲阜市| 克拉玛依市| 察哈| 定兴县| 阜康市| 东莞市| 临汾市| 巩义市| 项城市| 沙洋县| 湘阴县| 利川市| 绥棱县| 静海县| 卢湾区| 平乡县| 祁连县| 秦安县| 山东省| 西乌珠穆沁旗| 易门县| 曲阜市| 潞西市| 南靖县| 中卫市| 盘山县| 汝州市| 长武县| 集安市| 任丘市| 龙海市| 扬中市| 凤凰县| 田阳县| 林周县| 剑河县| 伊宁市| 贺州市| 东海县| 石家庄市| 新乐市|