zoukankan      html  css  js  c++  java
  • Java动态代理

    参考:http://www.360doc.com/content/14/0618/11/454045_387708106.shtml

       http://blog.csdn.net/heyutao007/article/details/49738887

    推荐:http://paddy-w.iteye.com/blog/841798

    JAVA的动态代理 
    代理模式 
    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 
    按照代理的创建时期,代理类可以分为两种。 
    静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 
    动态代理:在程序运行时,运用反射机制动态创建而成。 

    动态代理的两种实现:

    1.JDK动态代理。

    2.CGLIB动态代理。

    两种实现比较:

    jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。

    1.JDK动态代理demo

    1 package proxy;
    2 
    3 public interface UserService {
    4     
    5     public String getName(int name);
    6     
    7     public Integer getAge(int age);
    8 
    9 }
     1 package proxy;
     2 
     3 public class UserServiceImpl implements UserService {
     4 
     5     @Override
     6     public String getName(int name) {
     7         // TODO Auto-generated method stub
     8         System.out.println("----- getName  -----");
     9         return "Tom";
    10     }
    11 
    12     @Override
    13     public Integer getAge(int age) {
    14         // TODO Auto-generated method stub
    15         System.out.println("----- getAge  -----");
    16         return 10;
    17     }
    18 }
     1 package proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 
     6 public class MyInvocationHandler implements InvocationHandler {
     7     
     8     private Object target;
     9     
    10     public MyInvocationHandler() {
    11         // TODO Auto-generated constructor stub
    12         super();
    13     }
    14     
    15     public MyInvocationHandler(Object target) {
    16         this.target = target;
    17     }
    18 
    19     @Override
    20     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    21         // TODO Auto-generated method stub
    22         if("getName".equals(method.getName())) {
    23             System.out.println("+++++ before " + method.getName() + " +++++");
    24             Object result = method.invoke(target, args);
    25             System.out.println("+++++ after " + method.getName() + " +++++");
    26             return result;
    27         } else {
    28             Object result = method.invoke(target, args);
    29             return result;
    30         }
    31     }
    32 
    33 }
     1 package proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Proxy;
     5 
     6 public class Main1 {
     7     
     8     public static void main(String[] args) {
     9         UserService userService = new UserServiceImpl();
    10         InvocationHandler invocationHandler = new MyInvocationHandler(userService);
    11         UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler);
    12         System.out.println(userServiceProxy.getName(1));
    13         System.out.println(userServiceProxy.getAge(1));
    14     }
    15 
    16 }

    2.CGLIB动态代理demo

     1 package proxy;
     2 
     3 import java.lang.reflect.Method;
     4 
     5 import net.sf.cglib.proxy.MethodInterceptor;
     6 import net.sf.cglib.proxy.MethodProxy;
     7 
     8 public class CglibProxy implements MethodInterceptor {
     9 
    10     @Override
    11     public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    12         System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
    13         System.out.println(method.getName());
    14         Object o1 = methodProxy.invokeSuper(o, args);
    15         System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
    16         return o1;
    17     }
    18 }
     1 package proxy;
     2 
     3 import net.sf.cglib.proxy.Enhancer;
     4 
     5 public class Main2 {
     6     
     7     public static void main(String[] args) {  
     8         CglibProxy cglibProxy = new CglibProxy();  
     9   
    10         Enhancer enhancer = new Enhancer();  
    11         enhancer.setSuperclass(UserServiceImpl.class);  
    12         enhancer.setCallback(cglibProxy);  
    13   
    14         UserService o = (UserService)enhancer.create();  
    15         o.getName(1);  
    16         o.getAge(1);  
    17     }  
    18 
    19 }

    参数:Object为由CGLib动态生成的代理类实例,Method为上文中实体类所调用的被代理的方法引用,Object[]为参数值列表,MethodProxy为生成的代理类对方法的代理引用。

    参考:https://segmentfault.com/q/1010000002652067 

    为什么cglib不能拦截静态方法是因为Cglib的实现方式:生成的代理类继承自被代理类/目标类,请求时,执行自己织入的增强,然后再执行目标方法,因而使用继承方式创建代理类不能代理任何final方法和类,以及静态方法。

  • 相关阅读:
    HDU 5640 King's Cake
    HDU 5615 Jam's math problem
    HDU 5610 Baby Ming and Weight lifting
    WHU1604 Play Apple 简单博弈
    HDU 1551 Cable master 二分
    CodeForces659C Tanya and Toys map
    Codeforces 960E 树dp
    gym 101485E 二分匹配
    Codeforces 961E 树状数组,思维
    Codeforces Round #473 (Div. 2) D 数学,贪心 F 线性基,模板
  • 原文地址:https://www.cnblogs.com/microcat/p/6306898.html
Copyright © 2011-2022 走看看