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方法和类,以及静态方法。

  • 相关阅读:
    读取web.xml中设置的参数
    在服务端中,读取properties资源文件中的数据
    window下,nodejs安装http-server,并开启HTTP服务器
    跨域请求资源的方式
    IView 给Submenu增加click事件失效解决方案
    Vue -- mounted方法中调用methods的方法(并取出mounted方法中回调函数的值)
    IView 使用Table组件时实现给某一列添加click事件
    物联网协议CoAP协议学习
    电脑操作
    物联网协议
  • 原文地址:https://www.cnblogs.com/microcat/p/6306898.html
Copyright © 2011-2022 走看看