您的位置:首页 > 编程语言 > Java开发

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

2007-04-16 13:34 459 查看
注:本文转自我的javaeye博客 http://lixuehui.javaeye.com/blog/71314 上面有magicframework源代码,可以下载

[align=left]看了一看springframework的源代码,IOC和AOP部分值得学习.我也写了一个能够具有同样功能的框架,IOC和AOP,(前后花了8个小时的时间),虽然都实现了IOC和AOP功能,不过扩展性,以及其它特性不及spring的强大了,主要是让大家了解一下spring的内部实现机制和设计思想是什么样的,其实我们也可以设计自己的框架,就是这么简单.[/align]
[align=left]不罗嗦了,开始讲了.... [/align]
[align=left]1,2节为讨论AOP和IOC的底层实现原理,如果对这两部分了解的同学请直接看第三节[/align]
[align=left]1, 先谈谈AOP的底层是如何实现的吧[/align]
[align=left]动态代理来实现AOP,已经不是一个时髦的话题了,但是今天再拿出来再嚼一嚼,体会体会,恐怕大家仿佛也会有更多东西理解的更为深刻一些。[/align]
[align=left]恐怕在java的反射机制被创造出来的时候,那些大师们也没曾想到,反射的发展导致AOP会如此流行,无论是事务处理还是权限处理,getHibernateTemplate的session开启与关闭,无不显现着AOP的身影,spring对aop的应用之广泛,另很多问题化简为易。[/align]
[align=left]
下面就用一个java的动态代理的例子阐述一下AOP的实现思路。[/align]
[align=left]java 代码[/align]

[align=left]1. 1,首先,简单的接口,简单的实现 [/align]
[align=left]2. public interface MyFace { [/align]
[align=left]3. public String hello(); [/align]
[align=left]4. } [/align]
[align=left]5. public class MyFaceImpl implements MyFace { [/align]
[align=left]6. public String hello() { [/align]
[align=left]7. System.out.println("Hello,World!"); [/align]
[align=left]8. return "Hello,World!"; [/align]
[align=left]9. } [/align]
[align=left]10. } [/align]
[align=left]11. 动态代理助手类 [/align]
[align=left]12. import java.lang.reflect.InvocationHandler; [/align]
[align=left]13. import java.lang.reflect.Method; [/align]
[align=left]14. import java.lang.reflect.Proxy; [/align]
[align=left]15. [/align]
[align=left]16. public class DynamicProxyHandler implements InvocationHandler { [/align]
[align=left]17. // 定义需要代理的目标对象 [/align]
[align=left]18. private Object target; [/align]
[align=left]19. [/align]
[align=left]20. // 设置代理目标对象 [/align]
[align=left]21. Object setObject(Object target) { [/align]
[align=left]22. this.target = (Object) target; [/align]
[align=left]23. Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(), [/align]
[align=left]24. target.getClass().getInterfaces(), this); [/align]
[align=left]25. //这里第三个参数是实现InvocationHandler对象,在下面main方法中调用hello()时就是调用传入的这个对象里的invoke方法,通过传入的第 [/align]
[align=left]26. [/align]
[align=left]27. 一和第二个参数classloader和这个类实现的接口反射出方法来,以便执行真实方法中的内容,可以在真实方法执行的前后任意施展。 [/align]
[align=left]28. return obj; [/align]
[align=left]29. } [/align]
[align=left]30. [/align]
[align=left]31. public Object invoke(Object proxy, Method method, Object[] args) [/align]
[align=left]32. throws Throwable { [/align]
[align=left]33. System.out.println("Before method" + method.getName()); [/align]
[align=left]34. /** [/align]
[align=left]35. * 这里可以实现接口编程,依赖注入实现,动态去实现这部分的代码 [/align]
[align=left]36. * 真正达到AOP效果 [/align]
[align=left]37. * [/align]
[align=left]38. */ [/align]
[align=left]39. method.invoke(target, args); [/align]
[align=left]40. System.out.println("After method" + method.getName()); [/align]
[align=left]41. return null; [/align]
[align=left]42. } [/align]
[align=left]43. } [/align]
[align=left]44. 测试类 [/align]
[align=left]45. public class Test { [/align]
[align=left]46. [/align]
[align=left]47. public static void main(String[] args) { [/align]
[align=left]48. MyFace impl = new MyFaceImpl(); [/align]
[align=left]49. [/align]
[align=left]50. DynamicProxyHandler hander = new DynamicProxyHandler(); [/align]
[align=left]51. [/align]
[align=left]52. MyFace myface = (MyFace) hander.setObject(impl); [/align]
[align=left]53. //这个myface对象,已经不是简单意义上的MyFaceImpl的实例,而是MyFace的一个代理。 [/align]
[align=left]54. [/align]
[align=left]55. [/align]
[align=left]56. myface.hello(); [/align]
[align=left]57. //由于myface是个代理,所以调用hello方法时,进入的是DynamicProxyHandler中的invoke,通过反射执行它的实现 [/align]
[align=left]58. [/align]
[align=left]59. MyFaceImpl中的方法。 [/align]
[align=left]60. } [/align]
[align=left]61. } [/align]
[align=left]62. 控制台输出: [/align]
[align=left]63. Before methodhello [/align]
[align=left]64. Hello,World! [/align]
[align=left]65. After methodhello [/align]

[align=left]一组干干净净的接口与接口的实现,没有与外界有任何的联系,经过一番包装,达到了方法拦截的效果,通过动态代理类实现AOP,说一千,道[/align]
[align=left]一万,都是对反射机制的运用,连ioc也是反射机制的巧妙实现。[/align]
[align=left]动态代理的实质是:创造出一个需要被AOP的类的对象的一个替代品,这个替代品身上含有原对象的一切属性(实现的接口,classloader),然[/align]
[align=left]后这个替代品会调用自己的方法(invoke),在这个方法里通过反射,反射出需要被AOP的那个对象,以及它的方法,执行,在执行前后,替代品[/align]
[align=left]可以做一些另外的事情,在外界看来,就在原对象方法执行的前后被绑定了一些其他的操作。[/align]
[align=left]举个例子来说说:[/align]
[align=left]java 代码[/align]

[align=left]1. 1,你的老板想买一台笔记本电脑,正常是话,是他自己亲自去买,到电脑城,问问价钱,付帐,完事, [/align]
[align=left]2. MyFace myface = new MyFaceImpl(); //创建老板对象 [/align]
[align=left]3. myface.hello(); //买电脑操作 [/align]
[align=left]4. 2,但是他现在觉得他是老板,这件事应该派他的秘书去买,因为秘书可以和商家侃侃价什么的,他不好意思那么做,于是他让他的秘书去了 [/align]
[align=left]5. DynamicProxyHandler hander = new DynamicProxyHandler(); //创建一个秘书(代理助手类) [/align]
[align=left]6. MyFace myface = (MyFace) hander.setObject(impl); //将这个秘书安排为做这个老板的秘书 [/align]
[align=left]7. 3,秘书到了电脑城看了很多牌子,眼都看花了,最后打个电话问问老板到底买哪款,最后老板决定说购买lenovo ThinkPad T60. [/align]
[align=left]8. DynamicProxyHandler hander = new DynamicProxyHandler(); [/align]
[align=left]9. MyFace myface = (MyFace) hander.setObject(impl); [/align]
[align=left]10. myface.hello(); //这个myface就是秘书(代理类) 执行这个hello,是秘书在买电脑,而不是老板,因此执行的是 [/align]
[align=left]11. //而且Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);这个时候传的 [/align]
[align=left]12. [/align]
[align=left]13. 第三个对象是DynamicProxyHander对象本身,因此执行它其中的invoke方法 [/align]
[align=left]14. [/align]
[align=left]15. DynamicProxyHandler中的invoke(Object proxy, Method method, Object[] args)方法。 [/align]
[align=left]16. [/align]
[align=left]17. 打电话问问老板到底买哪款 [/align]
[align=left]18. 相当与invoke方法中的method.invoke(target, args); // 呼叫原类的hello方法,问老板,让他决定买哪个 [/align]
[align=left]19. [/align]
[align=left]20. [/align]
[align=left]21. 4,老板告诉她以后,她与经销商侃了侃价,付帐,临走又给了点小费。 [/align]
[align=left]22. public Object invoke(Object proxy, Method method, Object[] args) [/align]
[align=left]23. throws Throwable { [/align]
[align=left]24. System.out.println("Before method" + method.getName()); //侃侃价 [/align]
[align=left]25. method.invoke(target, args); [/align]
[align=left]26. System.out.println("After method" + method.getName()); //给小费 [/align]
[align=left]27. return null; [/align]
[align=left]28. } [/align]

[align=left]AOP大概其就是这么实现的,下面谈一谈IOC是如何实现的吧.[/align]
[align=left]2,IOC的实现原理[/align]
[align=left] [/align]
[align=left] IOC也是利用JAVA的反射机制,IOC注重的是代码关系之间的无侵入性,具体来说spring更注意这个特点,就是说要将代码之间的关系隔离到代码外部,在xml文件中进行配置,每当代码结构变更时,双方的代码都不要被改动即可实现移植.[/align]
[align=left]"如果你需要一个东西,那么不是你自己去取,而是发个指令,有人会送给你","站着别动,我来找你".[/align]
[align=left]这两句话什么意思呢,比方说[/align]
[align=left]java 代码[/align]

[align=left]1. public UserServiceImpl{ [/align]
[align=left]2. UserDao userDao; [/align]
[align=left]3. setUserDao(UserDao userDao){ [/align]
[align=left]4. this.userDao = userDao; [/align]
[align=left]5. } [/align]
[align=left]6. } [/align]

[align=left] [/align]
[align=left]这个userDao,不需要UserServiceImpl自己去创建这个UserDao对象,由IOC容器主动根据UserServiceImpl提供的setUserDao将UserDao实现的对象赋给userDao,这种用set函数设值的方式有叫做type3,用构造器设值叫做type2,用接口设值成为type1.[/align]
[align=left]那么怎么才能在运行时期把userDao设置上去呢,答案是通过反射机制,在运行时,通过反射反射出UserDao的实现类的对象,并通过反射得到UserServiceImpl的setUserDao方法,将刚才反射得到的UserDao实现类的对象传给setUserDao方法,就完成了设值工作。[/align]
[align=left]这些设值的工作是在加载spring文件构造Bean工厂的时候就完成的.所以启动完毕,每个对象中的需要注射的属性是有值的.[/align]
[align=left]就是这样的达到容器管理Bean的效果.[/align]
[align=left] [/align]
[align=left]好了,罗嗦了这么多,下面才是本篇的核心[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]3,magiaframework框架核心代码全解[/align]
[align=left]1,首先是一组接口与实现。[/align]
[align=left]java 代码[/align]

[align=left]1. public interface MyContext { [/align]
[align=left]2. public MyBeanFactory getMyBeanFacoty(); [/align]
[align=left]3. } [/align]
[align=left]4. /** [/align]
[align=left]5. * 本类负责管理和维护bean的工厂 [/align]
[align=left]6. * [/align]
[align=left]7. * [/align]
[align=left]8. * @author lixuehui [/align]
[align=left]9. * [/align]
[align=left]10. */ [/align]
[align=left]11. public class MyXmlClasspathContext implements MyContext { [/align]
[align=left]12. public static Map beanMap = new HashMap(); [/align]
[align=left]13. [/align]
[align=left]14. // private static MyContext context = new MyXmlClasspathContext(); [/align]
[align=left]15. [/align]
[align=left]16. public MyBeanFactory getMyBeanFacoty() { [/align]
[align=left]17. return new MyBeanFactory(beanMap); [/align]
[align=left]18. } [/align]
[align=left]19. [/align]
[align=left]20. private MyXmlClasspathContext() { [/align]
[align=left]21. [/align]
[align=left]22. } [/align]
[align=left]23. [/align]
[align=left]24. // 为了支持多配置文件并存的现象 [/align]
[align=left]25. private MyXmlClasspathContext(String[] xml) { [/align]
[align=left]26. // 逐个xml文件解析,将所有的bean一起放在最终的大Map里边去 [/align]
[align=left]27. [/align]
[align=left]28. } [/align]
[align=left]29. [/align]
[align=left]30. public MyXmlClasspathContext(String xml) { [/align]
[align=left]31. // 根据xml得到它内部的一些bean的信息 [/align]
[align=left]32. // 一个大map,大map里放着MyBean对象,MyBean对象中含有属性map [/align]
[align=left]33. // Map beanMap = new HashMap(); [/align]
[align=left]34. MyBean myBean = null; [/align]
[align=left]35. Map propTempMap = null; [/align]
[align=left]36. int aopcount = 0; [/align]
[align=left]37. try { [/align]
[align=left]38. SAXReader reader = new SAXReader(); [/align]
[align=left]39. Document doc = reader.read(new File(xml)); [/align]
[align=left]40. Element root = doc.getRootElement(); [/align]
[align=left]41. Element foo; [/align]
[align=left]42. for (Iterator i = root.elementIterator("bean"); i.hasNext();) { [/align]
[align=left]43. myBean = new MyBean(); [/align]
[align=left]44. [/align]
[align=left]45. foo = (Element) i.next(); [/align]
[align=left]46. for (Iterator j = foo.elementIterator("property"); j.hasNext();) { [/align]
[align=left]47. Element foo2 = (Element) j.next(); [/align]
[align=left]48. Attribute name = foo2.attribute("name"); [/align]
[align=left]49. Attribute ref = foo2.attribute("ref"); [/align]
[align=left]50. [/align]
[align=left]51. Attribute methodname = foo2.attribute("methodname"); [/align]
[align=left]52. [/align]
[align=left]53. if (methodname != null) { [/align]
[align=left]54. } [/align]
[align=left]55. // StringBuffer result = new StringBuffer(name.getValue()); [/align]
[align=left]56. // if (ref != null) { [/align]
[align=left]57. // result.append("/t" + ref.getValue()); [/align]
[align=left]58. // } [/align]
[align=left]59. // property结点的两个属性值 name 和 ref被得到 [/align]
[align=left]60. if (methodname == null) { [/align]
[align=left]61. myBean.addPropertyElement(name.getValue(), ref [/align]
[align=left]62. .getValue()); [/align]
[align=left]63. } else { [/align]
[align=left]64. myBean.addPropertyElement("aopM" + aopcount, methodname [/align]
[align=left]65. .getValue()); [/align]
[align=left]66. } [/align]
[align=left]67. } [/align]
[align=left]68. Attribute id = foo.attribute("id"); [/align]
[align=left]69. Attribute cls = foo.attribute("class"); [/align]
[align=left]70. Attribute aop = foo.attribute("aop"); [/align]
[align=left]71. Attribute aoptype = foo.attribute("aoptype"); [/align]
[align=left]72. if (aop != null || aoptype != null) { [/align]
[align=left]73. myBean.setAop(aop.getValue()); [/align]
[align=left]74. myBean.setAoptype(aoptype.getValue()); [/align]
[align=left]75. } [/align]
[align=left]76. myBean.setId(id.getValue()); [/align]
[align=left]77. myBean.setClasstarget(cls.getValue()); [/align]
[align=left]78. // 构造装bean的大Map!!! [/align]
[align=left]79. beanMap.put(id.getValue(), myBean); [/align]
[align=left]80. // 构造完的这个bean的大Map,以单例的形式放在内存中 [/align]
[align=left]81. propTempMap = null; [/align]
[align=left]82. myBean = null; [/align]
[align=left]83. } [/align]
84.
[align=left]85. } catch (Exception e) { [/align]
[align=left]86. e.printStackTrace(); [/align]
[align=left]87. } [/align]
[align=left]88. } [/align]
[align=left]89. [/align]
[align=left]90. } [/align]

[align=left] [/align]
[align=left]以上的public MyXmlClasspathContext(String xml),是传入配置文件,根据配置文件,构造MyBeanFactory对象,也就是IOC一节讲的Bean工厂,就是一个对XML进行解析的过程,将xml中的参数,读取封装为单个的MyBean对象,放入一个大的Map中,这个大的Map便是生产加工Bean的工厂。[/align]
[align=left]java 代码[/align]

[align=left]1. /** [/align]
[align=left]2. * Bean工厂接口 [/align]
[align=left]3. * [/align]
[align=left]4. * @author lixuehui [/align]
[align=left]5. * [/align]
[align=left]6. */ [/align]
[align=left]7. public interface BeanFactory { [/align]
[align=left]8. public Object getMyBean(String beanName); [/align]
[align=left]9. } [/align]

[align=left]java 代码[/align]

[align=left]1. [/align]
[align=left]2. /** [/align]
[align=left]3. * 本类负责管理和维护bean的工厂 [/align]
[align=left]4. * [/align]
[align=left]5. * [/align]
[align=left]6. * @author lixuehui [/align]
[align=left]7. * [/align]
[align=left]8. * msn:xuehui_lee@hotmail.com [/align]
[align=left]9. * [/align]
[align=left]10. * [/align]
[align=left]11. */ [/align]
[align=left]12. public class MyBeanFactory implements BeanFactory { [/align]
[align=left]13. private static Logger log = Logger.getLogger(MyBeanFactory.class); [/align]
[align=left]14. [/align]
[align=left]15. Map beanMap; // 用来存放bean对象的大Map [/align]
[align=left]16. [/align]
[align=left]17. public MyBeanFactory(Map beanMap) { [/align]
[align=left]18. this.beanMap = beanMap; [/align]
[align=left]19. } [/align]
[align=left]20. [/align]
[align=left]21. public Object getMyBean(String beanName) { [/align]
[align=left]22. // 根据bean名从beanMap里去提取Bean名 [/align]
[align=left]23. MyBean myBean = (MyBean) beanMap.get(beanName); [/align]
[align=left]24. // Bean中的property存放在Map中,property中存放着哪些对象需要注射,注射给谁的信息 [/align]
[align=left]25. Map propMap = myBean.getPropertys(); [/align]
[align=left]26. Object oldtarget = null; // 属性需要注射的对象 [/align]
[align=left]27. Class c1; [/align]
[align=left]28. try { [/align]
[align=left]29. // 这里是不需要方法拦截的情况 [/align]
[align=left]30. // 反射出需要注射的对象 [/align]
[align=left]31. c1 = Class.forName(myBean.getClasstarget()); [/align]
[align=left]32. oldtarget = c1.newInstance(); [/align]
[align=left]33. [/align]
[align=left]34. if (myBean.getAop() != null) { [/align]
[align=left]35. // 调用动态代理 来实现这个Bean [/align]
[align=left]36. AopHandler hander = new AopHandler(); [/align]
[align=left]37. [/align]
[align=left]38. String aopClass = myBean.getAop(); [/align]
[align=left]39. MyBean aopBean = (MyBean) beanMap.get(aopClass); [/align]
[align=left]40. [/align]
[align=left]41. MyAdvisor advisor = (MyAdvisor) Class.forName( [/align]
[align=left]42. aopBean.getClasstarget()).newInstance(); [/align]
[align=left]43. [/align]
[align=left]44. if ("before".equals(myBean.getAoptype())) { [/align]
[align=left]45. hander.setBeforeAdvisor(advisor); [/align]
[align=left]46. } else { [/align]
[align=left]47. hander.setAfterAdvisor(advisor); [/align]
[align=left]48. } [/align]
[align=left]49. Object obj = hander.setObject(oldtarget); [/align]
[align=left]50. [/align]
[align=left]51. Set keySet = propMap.keySet(); [/align]
[align=left]52. [/align]
[align=left]53. for (Iterator iter = keySet.iterator(); iter.hasNext();) { [/align]
[align=left]54. String key = (String) iter.next(); [/align]
[align=left]55. String value = (String) propMap.get(key); [/align]
[align=left]56. // 也就是说把需要注射的类的key属性注射为value对应的对象即可 [/align]
[align=left]57. MyBean taget = (MyBean) beanMap.get(value); [/align]
[align=left]58. // 2, 反射出被注射的bean的对象 [/align]
[align=left]59. Class c2 = Class.forName(taget.getClasstarget()); [/align]
[align=left]60. // 将key的第一个字母变为大写的 [/align]
[align=left]61. StringBuffer tempStr = new StringBuffer(key); [/align]
[align=left]62. Method method = c1.getMethod("set" [/align]
[align=left]63. + tempStr.substring(0, 1).toUpperCase() [/align]
[align=left]64. + tempStr.deleteCharAt(0), c2.getInterfaces()[0]); [/align]
[align=left]65. method.invoke(oldtarget, new Object[] { c2.newInstance() }); [/align]
[align=left]66. } [/align]
[align=left]67. return obj; [/align]
[align=left]68. [/align]
[align=left]69. } else { // 以下是不需要方法拦截的情况下是这么做的 [/align]
[align=left]70. [/align]
[align=left]71. // 以下从beanMap中得到属性需要注射的这个对象的内部信息,获知哪些属性需要需要注射,注射什么,注射成什么 [/align]
[align=left]72. Set keySet = propMap.keySet(); [/align]
[align=left]73. for (Iterator iter = keySet.iterator(); iter.hasNext();) { [/align]
[align=left]74. String key = (String) iter.next(); [/align]
[align=left]75. String value = (String) propMap.get(key); [/align]
[align=left]76. // 也就是说把需要注射的类的key属性注射为value对应的对象即可 [/align]
[align=left]77. MyBean taget = (MyBean) beanMap.get(value); [/align]
[align=left]78. // 2, 反射出被注射的bean的对象 [/align]
[align=left]79. Class c2 = Class.forName(taget.getClasstarget()); [/align]
[align=left]80. // 将key的第一个字母变为大写的 [/align]
[align=left]81. StringBuffer tempStr = new StringBuffer(key); [/align]
[align=left]82. // 反射出set方法,设置已接口定义的需要被注射的对象引用 [/align]
[align=left]83. Method method = c1.getMethod("set" [/align]
[align=left]84. + tempStr.substring(0, 1).toUpperCase() [/align]
[align=left]85. + tempStr.deleteCharAt(0), c2.getInterfaces()[0]); [/align]
[align=left]86. method.invoke(oldtarget, new Object[] { c2.newInstance() }); [/align]
[align=left]87. c2.newInstance(); [/align]
[align=left]88. } [/align]
[align=left]89. } [/align]
[align=left]90. } catch (Exception e) { [/align]
[align=left]91. e.printStackTrace(); [/align]
[align=left]92. } [/align]
[align=left]93. return oldtarget; [/align]
[align=left]94. } [/align]
[align=left]95. } [/align]

[align=left]以上,主要是个getMyBean方法,从Bean工厂中(大的装Bean的Map)里,根据Bean的名字获得Bean对象,以及通过反射机制获得原有对象,获得被注射的对象,以及用反射机制得到set方法的过程,完成IOC注射.[/align]
[align=left]注意,如果判断是需要AOP进行方法拦截的情况,则用动态代理类AopHandler来包装原始类,[/align]
[align=left] MyAdvisor advisor = (MyAdvisor) Class.forName(
aopBean.getClasstarget()).newInstance(); 得到在配置文件中配置的客户指定的方法拦截类.[/align]
[align=left] if ("before".equals(myBean.getAoptype())) {
hander.setBeforeAdvisor(advisor);
} else {
hander.setAfterAdvisor(advisor);
} //如果配置为before则是方法执行前拦截,反之,方法执行后拦截。[/align]
[align=left]java 代码[/align]

[align=left]1. [/align]
[align=left]2. public class AopHandler implements InvocationHandler { [/align]
[align=left]3. // 定义需要代理的目标对象 [/align]
[align=left]4. private Object target; [/align]
[align=left]5. [/align]
[align=left]6. MyAdvisor after; // 定义方法前置顾问 [/align]
[align=left]7. [/align]
[align=left]8. MyAdvisor before; // 定义方法后置顾问 [/align]
[align=left]9. [/align]
[align=left]10. // 设置代理目标对象 [/align]
[align=left]11. public Object setObject(Object target) { [/align]
[align=left]12. this.target = (Object) target; [/align]
[align=left]13. Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(), [/align]
[align=left]14. target.getClass().getInterfaces(), this); [/align]
[align=left]15. // 用newProxyInstance生成一个代理类,参数是传入的这个类的classloader,它的接口和实现InvocationHandler的对象 [/align]
[align=left]16. [/align]
[align=left]17. /** [/align]
[align=left]18. * 模拟这里的一些动作过程 1,根据classloader和接口 反射出对象 [/align]
[align=left]19. * [/align]
[align=left]20. * 2,调用DynamicProxyHandler类的invoke方法,把反射出来的对象传入,和根据反射生成的方法以及方法参数 [/align]
[align=left]21. * 达到AOP的效果 [/align]
[align=left]22. * [/align]
[align=left]23. */ [/align]
[align=left]24. return obj; [/align]
[align=left]25. } [/align]
[align=left]26. [/align]
[align=left]27. public Object invoke(Object proxy, Method method, Object[] args) [/align]
[align=left]28. throws Throwable { [/align]
[align=left]29. if (before != null) [/align]
[align=left]30. before.doInAdvisor(); [/align]
[align=left]31. // System.out.println("Before method" + method.getName()); [/align]
[align=left]32. // 这里注入要AOP的对象,它的方法在这里运行 [/align]
[align=left]33. method.invoke(target, args); [/align]
[align=left]34. // System.out.println("After method" + method.getName()); [/align]
[align=left]35. if (after != null) [/align]
[align=left]36. after.doInAdvisor(); [/align]
[align=left]37. // 这里注入要AOP的对象,它的方法在这里运行 [/align]
[align=left]38. return null; [/align]
[align=left]39. } [/align]
[align=left]40. [/align]
[align=left]41. public void setBeforeAdvisor(MyAdvisor advisor) { [/align]
[align=left]42. this.before = advisor; [/align]
[align=left]43. } [/align]
[align=left]44. [/align]
[align=left]45. public void setAfterAdvisor(MyAdvisor advisor) { [/align]
[align=left]46. this.after = advisor; [/align]
[align=left]47. } [/align]
[align=left]48. } [/align]
[align=left]49. public interface MyAdvisor { [/align]
[align=left]50. public void doInAdvisor(); [/align]
[align=left]51. } [/align]
[align=left]52. public class BeforeMethodAdvisor implements MyAdvisor { [/align]
[align=left]53. public void doInAdvisor() { [/align]
[align=left]54. System.out.println("This is Aops before!!"); [/align]
[align=left]55. } [/align]
[align=left]56. } [/align]
[align=left]57. public class AfterMethodAdvisor implements MyAdvisor { [/align]
[align=left]58. [/align]
[align=left]59. public void doInAdvisor() { [/align]
[align=left]60. System.out.println("This is Aops after!!"); [/align]
[align=left]61. } [/align]
[align=left]62. [/align]
[align=left]63. } [/align]

[align=left] [/align]
[align=left]1,AopHandler同AOP一节的动态代理类,实现对象代理功能[/align]
[align=left]2,MyAdvisor方法切面的一个接口[/align]
[align=left]3AfterMethodAdvisor和BeforeMethodAdvisor分别为实现MyAdvisor的扩展切面.[/align]
[align=left]使用时,与spring无类似[/align]
[align=left] [/align]
[align=left]java 代码[/align]

[align=left]1. MyBeanFactory facotry = new MyXmlClasspathContext("C://context.xml") [/align]
[align=left]2. .getMyBeanFacoty(); [/align]
[align=left]3. Object obj = facotry.getMyBean("userservice"); [/align]
[align=left]4. System.out.println(obj.getClass()); [/align]
[align=left]5. UserService userservice = (UserService) facotry [/align]
[align=left]6. .getMyBean("userservice"); [/align]
[align=left]7. userservice.myMethod(); [/align]

[align=left] [/align]
[align=left]同样,从Bean工厂中获得被注射完毕的Bean,进行使用,同时,可以达到配置实现AOP的目的.[/align]
[align=left]大体代码如上,我相信大家很容易看懂.[/align]
[align=left]再来介绍一下使用方法,我做了一个webdemo.[/align]
[align=left]和使用spring类似[/align]
[align=left]1,配置struts插件[/align]
[align=left] [/align]
[align=left]java 代码[/align]

[align=left]1. public class MySpringWebPlugin implements PlugIn { [/align]
[align=left]2. [/align]
[align=left]3. public void destroy() { [/align]
[align=left]4. } [/align]
[align=left]5. [/align]
[align=left]6. public void init(ActionServlet arg0, ModuleConfig arg1) [/align]
[align=left]7. throws ServletException { [/align]
[align=left]8. MyContext context = new MyXmlClasspathContext("/context.xml"); [/align]
[align=left]9. ServletContext servletContext = arg0.getServletContext(); [/align]
[align=left]10. servletContext.setAttribute(Constants.MYSPRING_CONFIG_NAME, context); [/align]
[align=left]11. MySpringServiceLocator.setServletContext(servletContext); [/align]
[align=left]12. } [/align]
[align=left]13. [/align]
[align=left]14. } [/align]

[align=left] 将magicframework上下文设置到servlet的上下文中。[/align]
[align=left]2,同时,用ServiceLocator的形式从servlet上下文中获取MagicFrameWork上下文.[/align]
[align=left]java 代码[/align]

[align=left]1. public class MySpringServiceLocator { [/align]
[align=left]2. private static MySpringServiceLocator locator; // = new [/align]
[align=left]3. [/align]
[align=left]4. // MySpringServiceLocator(); [/align]
[align=left]5. [/align]
[align=left]6. static MyBeanFactory beanFactory; [/align]
[align=left]7. [/align]
[align=left]8. private ServletContext servletContext; [/align]
[align=left]9. [/align]
[align=left]10. private MySpringServiceLocator() { [/align]
[align=left]11. [/align]
[align=left]12. } [/align]
[align=left]13. [/align]
[align=left]14. public UserService getUserService() { [/align]
[align=left]15. return (UserService) beanFactory.getMyBean("userservice"); [/align]
[align=left]16. } [/align]
[align=left]17. [/align]
[align=left]18. public static void setServletContext(ServletContext servletContext) { [/align]
[align=left]19. locator = new MySpringServiceLocator(); [/align]
[align=left]20. locator.servletContext = servletContext; [/align]
[align=left]21. } [/align]
[align=left]22. [/align]
[align=left]23. public static MySpringServiceLocator getInstance() { [/align]
[align=left]24. MyContext context = (MyContext) locator.servletContext [/align]
[align=left]25. .getAttribute(Constants.MYSPRING_CONFIG_NAME); [/align]
[align=left]26. beanFactory = context.getMyBeanFacoty(); [/align]
[align=left]27. return locator; [/align]
[align=left]28. } [/align]

[align=left] [/align]

[align=left]1. [/align]
[align=left]2. } [/align]

[align=left] [/align]
[align=left]xml 代码[/align]

[align=left]1. <?xml version="1.0" encoding="UTF-8"?> [/align]
[align=left]2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" [/align]
[align=left]3. xsi:noNamespaceSchemaLocation="magicframework.xsd"> [/align]
[align=left]4. [/align]
[align=left]5. <bean id="userdao" [/align]
[align=left]6. class="org.magicframework.demo.dao.UserDaoImpl"> [/align]
[align=left]7. </bean> [/align]
[align=left]8. [/align]
[align=left]9. <bean id="roledao" [/align]
[align=left]10. class="org.magicframework.demo.dao.RoleDaoImpl"> [/align]
[align=left]11. </bean> [/align]
[align=left]12. [/align]
[align=left]13. <bean id="userservice" [/align]
[align=left]14. class="org.magicframework.demo.service.UserServiceImpl" aop="myaop" [/align]
[align=left]15. aoptype="before"> [/align]
[align=left]16. <property name="userdao" ref="userdao" /> [/align]
[align=left]17. <property name="roledao" ref="roledao" /> [/align]
[align=left]18. </bean> [/align]
[align=left]19. [/align]
[align=left]20. <bean id="myaop" [/align]
[align=left]21. class="org.magicframework.demo.interceptor.MyTestBeforeMethodAdvisor"> [/align]
[align=left]22. <property methodname="myMethod" /> [/align]
[align=left]23. </bean> [/align]
[align=left]24. [/align]
[align=left]25. </beans> [/align]
[align=left]26. [/align]

[align=left] [/align]
[align=left]同时,xml配置如上,xsi:noNamespaceSchemaLocation="magicframework.xsd"> 这里我自己建立了XSD,所以引用本地的[/align]
[align=left]与spring类似,相信你能看的懂,我就不罗嗦了.[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息