posts - 15,  comments - 34,  trackbacks - 27
          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 2005-02-04 11:15 jacky 閱讀(1613) 評論(0)  編輯  收藏 所屬分類: Open source
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(10)

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          java

          搜索

          •  

          最新評論


          主站蜘蛛池模板: 洛浦县| 会同县| 霍州市| 定南县| 英山县| 泸水县| 遂昌县| 华蓥市| 吴忠市| 饶河县| 册亨县| 平武县| 太白县| 蛟河市| 昌图县| 崇明县| 灵寿县| 南皮县| 焉耆| 田阳县| 土默特左旗| 江安县| 抚远县| 陆河县| 巴彦淖尔市| 赤峰市| 布拖县| 乌审旗| 柘城县| 天祝| 兰考县| 丰原市| 克东县| 泽普县| 平和县| 唐河县| 松滋市| 望城县| 罗山县| 建始县| 池州市|