分享

Spring高级程序设计 5 Spring AOP基础

 KILLKISS 2012-09-28
1AOP概念 
AOP的核心概念: 
连接点(jointpoint):一个连接点是一个程序执行过程中的特定点。 
通知(advice):在某一特定的连接点处运行的代码成为“通知”。 
切入点(pointcut):切入点是用来定义某一个通知该何时执行的一组连接点。 
方面(aspect):通知和切入点的组合叫做方面。 
织入(weaving):织入是将方面真正的加入程序代码的过程。 
目标(target):如果一个对象的执行过程受到某个AOP操作的修改,那么他就叫做一个目标对象,也成为通知对象。 
引入(introduction):通过引入,我们可以在一个对象中加入新的方法或者字段,以改变他的结构。 

2AOP的类型 

两种类型AOP:静态AOP和动态AOP。 

静态代理: 
代理对象与被代理对象必须实现同一个接口。 
demo:
  1. package cn.partner4java.proxy.staticproxy;  
  2.   
  3.   
  4. /** 
  5. * 静态代理,统一接口 
  6. * @author partner4java 
  7. * 
  8. */  
  9. public interface IHello {  
  10.     /** 
  11.      * 可以带来的统一方法 
  12.      * @param name 
  13.      */  
  14.     public void hello(String name);  
  15. }  
  1. package cn.partner4java.proxy.staticproxy;  
  2.   
  3. /** 
  4. * 被代理的对象,需要借助代理对象加入日志 
  5. * @author partner4java 
  6. * 
  7. */  
  8. public class HelloSpeaker implements IHello {  
  9.   
  10.     public void hello(String name) {  
  11.         System.out.println("Hello " + name);  
  12.     }  
  13.   
  14. }  
  1. package cn.partner4java.proxy.staticproxy;  
  2.   
  3. /** 
  4. * 代理对象,给被代理对象添加日志 
  5. */  
  6. public class HelloProxy implements IHello {  
  7.       
  8.     private IHello iHello;  
  9.   
  10.     public HelloProxy(IHello iHello) {  
  11.         super();  
  12.         this.iHello = iHello;  
  13.     }  
  14.   
  15.   
  16.     public void hello(String name) {  
  17.         System.out.println("记录日志");  
  18.         iHello.hello(name);  
  19.     }  
  20.   
  21. }  
  1. package cn.partner4java.proxy.staticproxy;  
  2.   
  3. /** 
  4. * 调用 
  5. * @author partner4java 
  6. * 
  7. */  
  8. public class ProxyDemo {  
  9.   
  10.     public static void main(String[] args) {  
  11.         IHello iHello = new HelloProxy(new HelloSpeaker());  
  12.         iHello.hello("long");  
  13.     }  
  14.   
  15. }  




动态代理: 
动态代理区别于静态带来实现的地方在于织入过程是在运行时动态进行的。自己实现一般实现java.lang.reflect.InvocationHandler接口。 
例子:
  1. package cn.partner4java.proxy.dynamicproxy;  
  2.   
  3.   
  4. public interface IHello {  
  5.     public void hello(String name);  
  6. }  
  1. package cn.partner4java.proxy.dynamicproxy;  
  2.   
  3. /** 
  4. * 被代理的对象,需要借助代理对象加入日志 
  5. * @author partner4java 
  6. * 
  7. */  
  8. public class HelloSpeaker implements IHello {  
  9.   
  10.     public void hello(String name) {  
  11.         System.out.println("Hello " + name);  
  12.     }  
  13.   
  14. }  
  1. package cn.partner4java.proxy.dynamicproxy;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5. import java.lang.reflect.Proxy;  
  6.   
  7. /** 
  8. * 动态代理对象 
  9. * @author partner4java 
  10. * 
  11. */  
  12. public class LogHandler implements InvocationHandler {  
  13.   
  14.     private Object delegate;  
  15.       
  16.     public Object bind(Object delegate){  
  17.         this.delegate = delegate;  
  18.         return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),   
  19.                 delegate.getClass().getInterfaces(), this);  
  20.     }  
  21.     /** 
  22.      * 代理对象,这里面还可以改变原有的方法 
  23.      */  
  24.     public Object invoke(Object proxy, Method method, Object[] args)  
  25.             throws Throwable {  
  26.         Object result = null;  
  27.         try {  
  28.             System.out.println("添加日志");  
  29.             result = method.invoke(delegate, args);  
  30.         } catch (Exception e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.           
  34.         return null;  
  35.     }  
  36.   
  37. }  
  1. package cn.partner4java.proxy.dynamicproxy;  
  2.   
  3. /** 
  4. * 测试 
  5. * @author partner4java 
  6. * 
  7. */  
  8. public class ProxyDemo {  
  9.     public static void main(String[] args) {  
  10.         LogHandler logHandler = new LogHandler();  
  11.         IHello iHello = (IHello) logHandler.bind(new HelloSpeaker());  
  12.         iHello.hello("long");  
  13.     }  
  14. }  








3Spring中的AOP 

利用ProxyFactory连接CGLIB简单实现AOP:
 
加入包aopalliance.jar\cglib-nodep-2.1_3.jar 
demo:
  1. package cn.partner4java.proxy.proxyfactory;  
  2.   
  3. /** 
  4. * 被代理的对象 
  5. * @author partner4java 
  6. * 
  7. */  
  8. public class MessageWriter {  
  9.     public void writeMessage(){  
  10.         System.out.println("world!");  
  11.     }  
  12. }  
  1. package cn.partner4java.proxy.proxyfactory;  
  2.   
  3. import org.aopalliance.intercept.MethodInterceptor;  
  4. import org.aopalliance.intercept.MethodInvocation;  
  5.   
  6. /** 
  7. * 装饰者<br/> 
  8. * MethodInterceptor接口是对方法调用连接点实现包围通知的AOP联盟标准接口 
  9. * @author partner4java 
  10. * 
  11. */  
  12. public class MessageDecorator implements MethodInterceptor{  
  13.   
  14.     public Object invoke(MethodInvocation invocation) throws Throwable {  
  15.         System.out.print("Hello ");  
  16.         Object retVal = invocation.proceed();  
  17.         return retVal;  
  18.     }  
  19.   
  20. }  
  1. package cn.partner4java.proxy.proxyfactory;  
  2.   
  3. import org.springframework.aop.framework.ProxyFactory;  
  4.   
  5. /** 
  6. * 调用组装 
  7. * 这里最重要的部分是我们使用ProxyFactory来创建一个目标对象代理,同时织入通知  
  8. * @author partner4java 
  9. * 
  10. */  
  11. public class HelloWorldWeaver {  
  12.   
  13.     public static void main(String[] args) {  
  14.         //目标  
  15.         MessageWriter target = new MessageWriter();  
  16.           
  17.         //create the proxy  
  18.         ProxyFactory proxyFactory = new ProxyFactory();  
  19.           
  20.         proxyFactory.addAdvice(new MessageDecorator());  
  21.         proxyFactory.setTarget(target);  
  22.           
  23.         //获取返回被代理的目标  
  24.         MessageWriter proxy = (MessageWriter) proxyFactory.getProxy();  
  25.           
  26.         target.writeMessage();  
  27.         System.out.println("---");  
  28.         proxy.writeMessage();  
  29. //      后台打印:  
  30. //      world!  
  31. //      ---  
  32. //      World world!  
  33.     }  
  34.   
  35. }  




Spring内部两种实现代理的方法:JDK动态代理和CGLIB代理。 

ProxyFactory类控制着Spring AOP中的织入和创建代理的过程。 

141-155各种通知(前置、后置等等) 




4Spring里的通知者和切入点 
155-176 讲解手工实现接口来实现切入点的方法 




5代理详解 

代理的核心就是拦截方法调用,并在需要的时候执行匹配某方法的通知链。 

和CGLIB不同的是,JDK代理只能代理接口,不能代理类。 

使用JDK代理时,如何处理一个特定的方法调用的决定是在程序运行时做出的,也就是在每次方法被调用时。使用CGLIB代理可以边开这种处理方法,CGLIB会在运行中随时为代理创建新类的字节码,并尽可能的重用已经生成的类的字节码。 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多