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

本文介绍了AOP与IOC的基本原理及实现方式,并提供了一个具备这两种功能的轻量级框架magicframework的实现细节。

  注:本文转自我的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 类似 , 相信你能看的懂 , 我就不罗嗦了 .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值