打造本土IOC/AOP框架-magicframework 簡化了的spring


  注:本文轉自我的javaeye博客 http://lixuehui.javaeye.com/blog/71314 上面有magicframework源代碼,可以下載

看了一看 springframework 的源代碼, IOC AOP 部分值得學習 . 我也寫了一個能夠具有同樣功能的框架 ,IOC AOP,( 前后花了 8 個小時的時間 ), 雖然都實現了 IOC AOP 功能,不過擴展性,以及其它特性不及 spring 的強大了 , 主要是讓大家了解一下 spring 的內部實現機制和設計思想是什么樣的 , 其實我們也可以設計自己的框架 , 就是這么簡單 .
不羅嗦了 , 開始講了 ....
1,2 節為討論 AOP IOC 的底層實現原理,如果對這兩部分了解的同學請直接看第三節
1, 先談談 AOP 的底層是如何實現的吧
動態代理來實現 AOP ,已經不是一個時髦的話題了,但是今天再拿出來再嚼一嚼,體會體會,恐怕大家仿佛也會有更多東西理解的更為深刻一些。
恐怕在 java 的反射機制被創造出來的時候,那些大師們也沒曾想到,反射的發展導致 AOP 會如此流行,無論是事務處理還是權限處理, getHibernateTemplate session 開啟與關閉,無不顯現着 AOP 的身影, spring aop 的應用之廣泛,另很多問題化簡為易。

下面就用一個 java 的動態代理的例子闡述一下 AOP 的實現思路。
java 代碼
1.          1 ,首先,簡單的接口,簡單的實現   
2.          public  interface  MyFace {   
3.            public  String hello();   
4.          }   
5.          public  class  MyFaceImpl  implements  MyFace {   
6.            public  String hello() {   
7.            System.out.println( "Hello,World!" );   
8.             return  "Hello,World!" ;   
9.           }   
10.       }   
11.       動態代理助手類   
12.       import  java.lang.reflect.InvocationHandler;   
13.       import  java.lang.reflect.Method;   
14.       import  java.lang.reflect.Proxy;   
15.         
16.       public  class  DynamicProxyHandler  implements  InvocationHandler {   
17.         //  定義需要代理的目標對象   
18.         private  Object target;   
19.         
20.         //  設置代理目標對象   
21.        Object setObject(Object target) {   
22.          this .target = (Object) target;   
23.         Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(),   
24.           target.getClass().getInterfaces(),  this );   
25.       // 這里第三個參數是實現 InvocationHandler 對象,在下面 main 方法中調用 hello() 時就是調用傳入的這個對象里的 invoke 方法,通過傳入的第   
26.         
27.       一和第二個參數 classloader 和這個類實現的接口反射出方法來,以便執行真實方法中的內容,可以在真實方法執行的前后任意施展。   
28.          return  obj;   
29.        }   
30.           
31.         public  Object invoke(Object proxy, Method method, Object[] args)   
32.           throws  Throwable {   
33.         System.out.println( "Before method"  + method.getName());   
34.          /**  
35.          *  這里可以實現接口編程,依賴注入實現,動態去實現這部分的代碼 
36.          *   真正達到 AOP 效果 
37.          *     
38.          */   
39.         method.invoke(target, args);   
40.         System.out.println( "After method"  + method.getName());   
41.          return  null ;   
42.        }   
43.       }   
44.       測試類   
45.       public  class  Test {   
46.         
47.         public  static  void  main(String[] args) {   
48.         MyFace impl =  new  MyFaceImpl();   
49.         
50.         DynamicProxyHandler hander =  new  DynamicProxyHandler();   
51.         
52.         MyFace myface = (MyFace) hander.setObject(impl);   
53.       // 這個 myface 對象,已經不是簡單意義上的 MyFaceImpl 的實例,而是 MyFace 的一個代理。   
54.           
55.         
56.         myface.hello();   
57.          // 由於 myface 是個代理,所以調用 hello 方法時,進入的是 DynamicProxyHandler 中的 invoke ,通過反射執行它的實現      
58.         
59.         MyFaceImpl 中的方法。   
60.        }   
61.       }   
62.       控制台輸出:   
63.       Before methodhello   
64.       Hello,World!   
65.       After methodhello   
一組干干凈凈的接口與接口的實現,沒有與外界有任何的聯系,經過一番包裝,達到了方法攔截的效果,通過動態代理類實現 AOP ,說一千,道
一萬,都是對反射機制的運用,連 ioc 也是反射機制的巧妙實現。
動態代理的實質是:創造出一個需要被 AOP 的類的對象的一個替代品,這個替代品身上含有原對象的一切屬性(實現的接口, classloader ,
后這個替代品會調用自己的方法 (invoke), 在這個方法里通過反射,反射出需要被 AOP 的那個對象,以及它的方法,執行,在執行前后,替代品
可以做一些另外的事情,在外界看來,就在原對象方法執行的前后被綁定了一些其他的操作。
舉個例子來說說:
java 代碼
1.          1 ,你的老板想買一台筆記本電腦,正常是話,是他自己親自去買,到電腦城,問問價錢,付帳,完事,   
2.           MyFace myface =  new  MyFaceImpl();  // 創建老板對象   
3.           myface.hello();  // 買電腦操作   
4.          2 ,但是他現在覺得他是老板,這件事應該派他的秘書去買,因為秘書可以和商家侃侃價什么的,他不好意思那么做,於是他讓他的秘書去了   
5.           DynamicProxyHandler hander =  new  DynamicProxyHandler();  // 創建一個秘書(代理助手類)   
6.           MyFace myface = (MyFace) hander.setObject(impl);  // 將這個秘書安排為做這個老板的秘書   
7.          3 ,秘書到了電腦城看了很多牌子,眼都看花了,最后打個電話問問老板到底買哪款,最后老板決定說購買 lenovo ThinkPad T60.    
8.           DynamicProxyHandler hander =  new  DynamicProxyHandler();   
9.           MyFace myface = (MyFace) hander.setObject(impl);     
10.        myface.hello();  // 這個 myface 就是秘書(代理類)  執行這個 hello, 是秘書在買電腦,而不是老板,因此執行的是   
11.         // 而且 Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this); 這個時候傳的    
12.         
13.         第三個對象是 DynamicProxyHander 對象本身,因此執行它其中的 invoke 方法   
14.           
15.        DynamicProxyHandler 中的 invoke(Object proxy, Method method, Object[] args) 方法。   
16.           
17.         打電話問問老板到底買哪款   
18.         相當與 invoke 方法中的 method.invoke(target, args);  //  呼叫原類的 hello 方法,問老板,讓他決定買哪個   
19.           
20.           
21.       4 ,老板告訴她以后,她與經銷商侃了侃價,付帳,臨走又給了點小費。   
22.         public  Object invoke(Object proxy, Method method, Object[] args)   
23.           throws  Throwable {   
24.         System.out.println( "Before method"  + method.getName());  // 侃侃價   
25.         method.invoke(target, args);   
26.         System.out.println( "After method"  + method.getName());  // 給小費   
27.          return  null ;   
28.        }   
AOP 大概其就是這么實現的 , 下面談一談 IOC 是如何實現的吧 .
2,IOC 的實現原理
 
 IOC 也是利用 JAVA 的反射機制 ,IOC 注重的是代碼關系之間的無侵入性,具體來說 spring 更注意這個特點,就是說要將代碼之間的關系隔離到代碼外部 , xml 文件中進行配置 , 每當代碼結構變更時 , 雙方的代碼都不要被改動即可實現移植 .
" 如果你需要一個東西 , 那么不是你自己去取 , 而是發個指令,有人會送給你 "," 站着別動,我來找你 ".
這兩句話什么意思呢 , 比方說
java 代碼
1.          public  UserServiceImpl{   
2.               UserDao userDao;   
3.               setUserDao(UserDao userDao){   
4.                  this .userDao = userDao;   
5.               }   
6.          }  
 
這個 userDao, 不需要 UserServiceImpl 自己去創建這個 UserDao 對象 , IOC 容器主動根據 UserServiceImpl 提供的 setUserDao UserDao 實現的對象賦給 userDao, 這種用 set 函數設值的方式有叫做 type3, 用構造器設值叫做 type2, 用接口設值成為 type1.
那么怎么才能在運行時期把 userDao 設置上去呢 , 答案是通過反射機制 , 在運行時 , 通過反射反射出 UserDao 的實現類的對象 , 並通過反射得到 UserServiceImpl setUserDao 方法 , 將剛才反射得到的 UserDao 實現類的對象傳給 setUserDao 方法 , 就完成了設值工作。
這些設值的工作是在加載 spring 文件構造 Bean 工廠的時候就完成的 . 所以啟動完畢,每個對象中的需要注射的屬性是有值的 .
就是這樣的達到容器管理 Bean 的效果 .
 
好了 , 羅嗦了這么多 , 下面才是本篇的核心
 
 
3,magiaframework 框架核心代碼全解
1, 首先是一組接口與實現。
java 代碼
1.          public  interface  MyContext {   
2.               public  MyBeanFactory getMyBeanFacoty();   
3.          }   
4.          /**  
5.           *  本類負責管理和維護 bean 的工廠 
6.           *   
7.           *   
8.           * @author lixuehui  
9.           *   
10.        */   
11.       public  class  MyXmlClasspathContext  implements  MyContext {   
12.            public  static  Map beanMap =  new  HashMap();   
13.         
14.            // private static MyContext context = new MyXmlClasspathContext();   
15.         
16.            public  MyBeanFactory getMyBeanFacoty() {   
17.                return  new  MyBeanFactory(beanMap);   
18.           }   
19.         
20.            private  MyXmlClasspathContext() {   
21.         
22.           }   
23.         
24.            //  為了支持多配置文件並存的現象   
25.            private  MyXmlClasspathContext(String[] xml) {   
26.                //  逐個 xml 文件解析,將所有的 bean 一起放在最終的大 Map 里邊去   
27.         
28.           }   
29.         
30.            public  MyXmlClasspathContext(String xml) {   
31.                //  根據 xml 得到它內部的一些 bean 的信息   
32.                //  一個大 map, map 里放着 MyBean 對象 ,MyBean 對象中含有屬性 map   
33.                // Map beanMap = new HashMap();   
34.               MyBean myBean =  null ;   
35.               Map propTempMap =  null ;   
36.                int  aopcount =  0 ;   
37.                try  {   
38.                   SAXReader reader =  new  SAXReader();   
39.                   Document doc = reader.read( new  File(xml));   
40.                   Element root = doc.getRootElement();   
41.                   Element foo;   
42.                    for  (Iterator i = root.elementIterator( "bean" ); i.hasNext();) {   
43.                       myBean =  new  MyBean();   
44.         
45.                       foo = (Element) i.next();   
46.                        for  (Iterator j = foo.elementIterator( "property" ); j.hasNext();) {   
47.                           Element foo2 = (Element) j.next();   
48.                           Attribute name = foo2.attribute( "name" );   
49.                           Attribute ref = foo2.attribute( "ref" );   
50.         
51.                           Attribute methodname = foo2.attribute( "methodname" );   
52.         
53.                            if  (methodname !=  null ) {   
54.                           }   
55.                            // StringBuffer result = new StringBuffer(name.getValue());   
56.                            // if (ref != null) {   
57.                            // result.append("/t" + ref.getValue());   
58.                            // }   
59.                            // property 結點的兩個屬性值  name   ref 被得到   
60.                            if  (methodname ==  null ) {   
61.                               myBean.addPropertyElement(name.getValue(), ref   
62.                                       .getValue());   
63.                           }  else  {   
64.                               myBean.addPropertyElement( "aopM"  + aopcount, methodname   
65.                                       .getValue());   
66.                           }   
67.                       }   
68.                       Attribute id = foo.attribute( "id" );   
69.                       Attribute cls = foo.attribute( "class" );   
70.                       Attribute aop = foo.attribute( "aop" );   
71.                       Attribute aoptype = foo.attribute( "aoptype" );   
72.                        if  (aop !=  null  || aoptype !=  null ) {   
73.                           myBean.setAop(aop.getValue());   
74.                           myBean.setAoptype(aoptype.getValue());   
75.                       }   
76.                       myBean.setId(id.getValue());   
77.                       myBean.setClasstarget(cls.getValue());   
78.                        //  構造裝 bean 的大 Map!!!   
79.                       beanMap.put(id.getValue(), myBean);   
80.                        //  構造完的這個 bean 的大 Map, 以單例的形式放在內存中   
81.                       propTempMap =  null ;   
82.                       myBean =  null ;   
83.                   }   
84.         
85.               }  catch  (Exception e) {   
86.                   e.printStackTrace();   
87.               }   
88.           }   
89.         
90.       }   
 
以上的 public MyXmlClasspathContext(String xml), 是傳入配置文件,根據配置文件 , 構造 MyBeanFactory 對象 , 也就是 IOC 一節講的 Bean 工廠 , 就是一個對 XML 進行解析的過程,將 xml 中的參數 , 讀取封裝為單個的 MyBean 對象 , 放入一個大的 Map 中,這個大的 Map 便是生產加工 Bean 的工廠。
java 代碼
1.          /**  
2.           * Bean 工廠接口 
3.           *   
4.           * @author lixuehui  
5.           *   
6.           */   
7.          public  interface  BeanFactory {   
8.               public  Object getMyBean(String beanName);   
9.          }  
java 代碼
1.            
2.          /**  
3.           *  本類負責管理和維護 bean 的工廠 
4.           *   
5.           *   
6.           * @author lixuehui  
7.           *   
8.           * msn:xuehui_lee@hotmail.com  
9.           *   
10.        *   
11.        */   
12.       public  class  MyBeanFactory  implements  BeanFactory {   
13.            private  static  Logger log = Logger.getLogger(MyBeanFactory. class );   
14.         
15.           Map beanMap;  //  用來存放 bean 對象的大 Map   
16.         
17.            public  MyBeanFactory(Map beanMap) {   
18.                this .beanMap = beanMap;   
19.           }   
20.         
21.            public  Object getMyBean(String beanName) {   
22.                //  根據 bean 名從 beanMap 里去提取 Bean   
23.               MyBean myBean = (MyBean) beanMap.get(beanName);   
24.                // Bean 中的 property 存放在 Map ,property 中存放着哪些對象需要注射 , 注射給誰的信息   
25.               Map propMap = myBean.getPropertys();   
26.               Object oldtarget =  null //  屬性需要注射的對象   
27.               Class c1;   
28.                try  {   
29.                    //  這里是不需要方法攔截的情況   
30.                    //  反射出需要注射的對象   
31.                   c1 = Class.forName(myBean.getClasstarget());   
32.                   oldtarget = c1.newInstance();   
33.         
34.                    if  (myBean.getAop() !=  null ) {   
35.                        //  調用動態代理  來實現這個 Bean   
36.                       AopHandler hander =  new  AopHandler();   
37.         
38.                       String aopClass = myBean.getAop();   
39.                       MyBean aopBean = (MyBean) beanMap.get(aopClass);   
40.         
41.                       MyAdvisor advisor = (MyAdvisor) Class.forName(   
42.                               aopBean.getClasstarget()).newInstance();   
43.         
44.                        if  ( "before" .equals(myBean.getAoptype())) {   
45.                           hander.setBeforeAdvisor(advisor);   
46.                       }  else  {   
47.                           hander.setAfterAdvisor(advisor);   
48.                       }   
49.                       Object obj = hander.setObject(oldtarget);   
50.         
51.                       Set keySet = propMap.keySet();   
52.         
53.                        for  (Iterator iter = keySet.iterator(); iter.hasNext();) {   
54.                           String key = (String) iter.next();   
55.                           String value = (String) propMap.get(key);   
56.                            //  也就是說把需要注射的類的 key 屬性注射為 value 對應的對象即可   
57.                           MyBean taget = (MyBean) beanMap.get(value);   
58.                            // 2,  反射出被注射的 bean 的對象   
59.                           Class c2 = Class.forName(taget.getClasstarget());   
60.                            //  key 的第一個字母變為大寫的   
61.                           StringBuffer tempStr =  new  StringBuffer(key);   
62.                           Method method = c1.getMethod( "set"   
63.                                   + tempStr.substring( 0 1 ).toUpperCase()   
64.                                   + tempStr.deleteCharAt( 0 ), c2.getInterfaces()[ 0 ]);   
65.                           method.invoke(oldtarget,  new  Object[] { c2.newInstance() });   
66.                       }   
67.                        return  obj;   
68.         
69.                   }  else  {  //  以下是不需要方法攔截的情況下是這么做的   
70.         
71.                        //  以下從 beanMap 中得到屬性需要注射的這個對象的內部信息,獲知哪些屬性需要需要注射,注射什么,注射成什么   
72.                       Set keySet = propMap.keySet();   
73.                        for  (Iterator iter = keySet.iterator(); iter.hasNext();) {   
74.                           String key = (String) iter.next();   
75.                           String value = (String) propMap.get(key);   
76.                            //  也就是說把需要注射的類的 key 屬性注射為 value 對應的對象即可   
77.                           MyBean taget = (MyBean) beanMap.get(value);   
78.                            // 2,  反射出被注射的 bean 的對象   
79.                           Class c2 = Class.forName(taget.getClasstarget());   
80.                            //  key 的第一個字母變為大寫的   
81.                           StringBuffer tempStr =  new  StringBuffer(key);   
82.                            //  反射出 set 方法,設置已接口定義的需要被注射的對象引用   
83.                           Method method = c1.getMethod( "set"   
84.                                   + tempStr.substring( 0 1 ).toUpperCase()   
85.                                   + tempStr.deleteCharAt( 0 ), c2.getInterfaces()[ 0 ]);   
86.                           method.invoke(oldtarget,  new  Object[] { c2.newInstance() });   
87.                           c2.newInstance();   
88.                       }   
89.                   }   
90.               }  catch  (Exception e) {   
91.                   e.printStackTrace();   
92.               }   
93.                return  oldtarget;   
94.           }   
95.       }   
以上,主要是個 getMyBean 方法,從 Bean 工廠中 ( 大的裝 Bean Map) , 根據 Bean 的名字獲得 Bean 對象 , 以及通過反射機制獲得原有對象 , 獲得被注射的對象 , 以及用反射機制得到 set 方法的過程,完成 IOC 注射 .
注意,如果判斷是需要 AOP 進行方法攔截的情況,則用動態代理類 AopHandler 來包裝原始類 ,
    MyAdvisor advisor = (MyAdvisor) Class.forName(
      aopBean.getClasstarget()).newInstance();
得到在配置文件中配置的客戶指定的方法攔截類 .
 if ("before".equals(myBean.getAoptype())) {
     hander.setBeforeAdvisor(advisor);
    } else {
     hander.setAfterAdvisor(advisor);
    } //
如果配置為 before 則是方法執行前攔截,反之,方法執行后攔截。
java 代碼
1.            
2.          public  class  AopHandler  implements  InvocationHandler {   
3.               //  定義需要代理的目標對象   
4.               private  Object target;   
5.            
6.              MyAdvisor after;  //  定義方法前置顧問   
7.            
8.              MyAdvisor before;  //  定義方法后置顧問   
9.            
10.            //  設置代理目標對象   
11.            public  Object setObject(Object target) {   
12.                this .target = (Object) target;   
13.               Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(),   
14.                       target.getClass().getInterfaces(),  this );   
15.                //  newProxyInstance 生成一個代理類 , 參數是傳入的這個類的 classloader, 它的接口和實現 InvocationHandler 的對象   
16.         
17.                /**  
18.                *  模擬這里的一些動作過程  1, 根據 classloader 和接口  反射出對象 
19.                *   
20.                * 2, 調用 DynamicProxyHandler 類的 invoke 方法,把反射出來的對象傳入 , 和根據反射生成的方法以及方法參數 
21.                *  達到 AOP 的效果 
22.                *   
23.                */   
24.                return  obj;   
25.           }   
26.         
27.            public  Object invoke(Object proxy, Method method, Object[] args)   
28.                    throws  Throwable {   
29.                if  (before !=  null )   
30.                   before.doInAdvisor();   
31.       //      System.out.println("Before method" + method.getName());   
32.                //  這里注入要 AOP 的對象,它的方法在這里運行   
33.               method.invoke(target, args);   
34.       //      System.out.println("After method" + method.getName());   
35.                if  (after !=  null )   
36.                   after.doInAdvisor();   
37.                //  這里注入要 AOP 的對象,它的方法在這里運行   
38.                return  null ;   
39.           }   
40.         
41.            public  void  setBeforeAdvisor(MyAdvisor advisor) {   
42.                this .before = advisor;   
43.           }   
44.         
45.            public  void  setAfterAdvisor(MyAdvisor advisor) {   
46.                this .after = advisor;   
47.           }   
48.       }   
49.       public  interface  MyAdvisor {   
50.            public  void  doInAdvisor();   
51.       }   
52.       public  class  BeforeMethodAdvisor  implements  MyAdvisor {   
53.            public  void  doInAdvisor() {   
54.               System.out.println( "This is Aops before!!" );   
55.           }   
56.       }   
57.       public  class  AfterMethodAdvisor  implements  MyAdvisor {   
58.         
59.            public  void  doInAdvisor() {   
60.               System.out.println( "This is Aops after!!" );   
61.           }   
62.         
63.       }   
 
1,AopHandler AOP 一節的動態代理類 , 實現對象代理功能
2,MyAdvisor 方法切面的一個接口
3AfterMethodAdvisor BeforeMethodAdvisor 分別為實現 MyAdvisor 的擴展切面 .
使用時 , spring 無類似
 
java 代碼
1.          MyBeanFactory facotry =  new  MyXmlClasspathContext( "C://context.xml" )   
2.           .getMyBeanFacoty();   
3.           Object obj = facotry.getMyBean( "userservice" );   
4.           System.out.println(obj.getClass());   
5.           UserService userservice = (UserService) facotry   
6.           .getMyBean( "userservice" );   
7.           userservice.myMethod();  
 
同樣,從 Bean 工廠中獲得被注射完畢的 Bean, 進行使用,同時,可以達到配置實現 AOP 的目的 .
大體代碼如上,我相信大家很容易看懂 .
再來介紹一下使用方法,我做了一個 webdemo.
和使用 spring 類似
1, 配置 struts 插件
 
java 代碼
1.          public  class  MySpringWebPlugin  implements  PlugIn {   
2.            
3.               public  void  destroy() {   
4.              }   
5.            
6.               public  void  init(ActionServlet arg0, ModuleConfig arg1)   
7.                       throws  ServletException {   
8.                  MyContext context =  new  MyXmlClasspathContext( "/context.xml" );   
9.                  ServletContext servletContext = arg0.getServletContext();   
10.               servletContext.setAttribute(Constants.MYSPRING_CONFIG_NAME, context);   
11.               MySpringServiceLocator.setServletContext(servletContext);   
12.           }   
13.         
14.       }  
  magicframework 上下文設置到 servlet 的上下文中。
2, 同時,用 ServiceLocator 的形式從 servlet 上下文中獲取 MagicFrameWork 上下文 .
java 代碼
1.          public  class  MySpringServiceLocator {   
2.               private  static  MySpringServiceLocator locator;  // = new   
3.            
4.               // MySpringServiceLocator();   
5.            
6.               static  MyBeanFactory beanFactory;   
7.            
8.               private  ServletContext servletContext;   
9.            
10.            private  MySpringServiceLocator() {   
11.         
12.           }   
13.         
14.            public  UserService getUserService() {   
15.                return  (UserService) beanFactory.getMyBean( "userservice" );   
16.           }   
17.         
18.            public  static  void  setServletContext(ServletContext servletContext) {   
19.               locator =  new  MySpringServiceLocator();   
20.               locator.servletContext = servletContext;   
21.           }   
22.         
23.            public  static  MySpringServiceLocator getInstance() {   
24.               MyContext context = (MyContext) locator.servletContext   
25.                       .getAttribute(Constants.MYSPRING_CONFIG_NAME);   
26.               beanFactory = context.getMyBeanFacoty();   
27.                return  locator;   
28.           }   
 
1.            
2.          }   
 
xml 代碼
1.          <? xml  version = "1.0"  encoding = "UTF-8"?>   
2.          < beans  xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"   
3.               xsi:noNamespaceSchemaLocation = "magicframework.xsd">   
4.            
5.               < bean  id = "userdao"   
6.                   class = "org.magicframework.demo.dao.UserDaoImpl">   
7.               </ bean >   
8.            
9.               < bean  id = "roledao"   
10.                class = "org.magicframework.demo.dao.RoleDaoImpl">   
11.            </ bean >   
12.         
13.            < bean  id = "userservice"   
14.                class = "org.magicframework.demo.service.UserServiceImpl"  aop = "myaop"   
15.                aoptype = "before">   
16.                < property  name = "userdao"  ref = "userdao"  />   
17.                < property  name = "roledao"  ref = "roledao"  />   
18.            </ bean >   
19.         
20.            < bean  id = "myaop"   
21.                class = "org.magicframework.demo.interceptor.MyTestBeforeMethodAdvisor">   
22.                < property  methodname = "myMethod"  />   
23.            </ bean >   
24.         
25.       </ beans >   
26.         
 
同時, xml 配置如上 , xsi:noNamespaceSchemaLocation = "magicframework.xsd">    這里我自己建立了 XSD, 所以引用本地的
spring 類似 , 相信你能看的懂 , 我就不羅嗦了 .

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com