欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java 动态代理的方法总结

程序员文章站 2024-03-03 17:06:52
java 动态代理的方法总结 aop的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行...

java 动态代理的方法总结

aop的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的interceptor的种类,如beforeadviseinterceptor,afteradviseinterceptor以及throwsadviseinterceptor等)。

那么动态代理是如何实现将切面逻辑(advise)织入到目标类方法中去的呢?下面我们就来详细介绍并实现aop中用到的两种动态代理。

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

1、定义接口和实现

package com.meituan.hyt.test3.service; 
 
 
public interface userservice { 
  public string getname(int id); 
 
  public integer getage(int id); 
} 

package com.meituan.hyt.test3.service.impl; 
 
import com.meituan.hyt.test3.service.userservice; 
 
 
public class userserviceimpl implements userservice { 
  @override 
  public string getname(int id) { 
    system.out.println("------getname------"); 
    return "tom"; 
  } 
 
  @override 
  public integer getage(int id) { 
    system.out.println("------getage------"); 
    return 10; 
  } 
} 

2、jdk动态代理实现

package com.meituan.hyt.test3.jdk; 
 
import java.lang.reflect.invocationhandler; 
import java.lang.reflect.method; 
 
 
public class myinvocationhandler implements invocationhandler { 
  private object target; 
 
  myinvocationhandler() { 
    super(); 
  } 
 
  myinvocationhandler(object target) { 
    super(); 
    this.target = target; 
  } 
 
  @override 
  public object invoke(object o, method method, object[] args) throws throwable { 
    if("getname".equals(method.getname())){ 
      system.out.println("++++++before " + method.getname() + "++++++"); 
      object result = method.invoke(target, args); 
      system.out.println("++++++after " + method.getname() + "++++++"); 
      return result; 
    }else{ 
      object result = method.invoke(target, args); 
      return result; 
    } 
 
  } 
} 
package com.meituan.hyt.test3.jdk; 
 
import com.meituan.hyt.test3.service.userservice; 
import com.meituan.hyt.test3.service.impl.userserviceimpl; 
 
import java.lang.reflect.invocationhandler; 
import java.lang.reflect.proxy; 
 
 
public class main1 { 
  public static void main(string[] args) { 
    userservice userservice = new userserviceimpl(); 
    invocationhandler invocationhandler = new myinvocationhandler(userservice); 
    userservice userserviceproxy = (userservice)proxy.newproxyinstance(userservice.getclass().getclassloader(), 
        userservice.getclass().getinterfaces(), invocationhandler); 
    system.out.println(userserviceproxy.getname(1)); 
    system.out.println(userserviceproxy.getage(1)); 
  } 
} 

运行结果

++++++before getname++++++
------getname------
++++++after getname++++++
tom
------getage------
10

3、cglib动态代理实现

cglib是一个优秀的动态代理框架,它的底层使用asm在内存中动态的生成被代理类的子类,使用cglib即使代理类没有实现任何接口也可以实现动态代理功能。cglib具有简单易用,它的运行速度要远远快于jdk的proxy动态代理:

cglib的核心类:

 net.sf.cglib.proxy.enhancer – 主要的增强类
  net.sf.cglib.proxy.methodinterceptor – 主要的方法拦截类,它是callback接口的子接口,需要用户实现
  net.sf.cglib.proxy.methodproxy – jdk的java.lang.reflect.method类的代理类,可以方便的实现对源对象方法的调用,如使用:
  object o = methodproxy.invokesuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。

net.sf.cglib.proxy.methodinterceptor接口是最通用的回调(callback)类型,它经常被基于代理的aop用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public object intercept(object object, java.lang.reflect.method method,
object[] args, methodproxy proxy) throws throwable;

第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.method对象的一般反射调用,或者使用 net.sf.cglib.proxy.methodproxy对象调用。net.sf.cglib.proxy.methodproxy通常被首选使用,因为它更快。

package com.meituan.hyt.test3.cglib; 
 
 
import net.sf.cglib.proxy.methodinterceptor; 
import net.sf.cglib.proxy.methodproxy; 
 
import java.lang.reflect.method; 
 
 
public class cglibproxy implements methodinterceptor { 
  @override 
  public object intercept(object o, method method, object[] args, methodproxy methodproxy) throws throwable { 
    system.out.println("++++++before " + methodproxy.getsupername() + "++++++"); 
    system.out.println(method.getname()); 
    object o1 = methodproxy.invokesuper(o, args); 
    system.out.println("++++++before " + methodproxy.getsupername() + "++++++"); 
    return o1; 
  } 
} 



package com.meituan.hyt.test3.cglib; 
 
import com.meituan.hyt.test3.service.userservice; 
import com.meituan.hyt.test3.service.impl.userserviceimpl; 
import net.sf.cglib.proxy.enhancer; 
 
 
 
public class main2 { 
  public static void main(string[] args) { 
    cglibproxy cglibproxy = new cglibproxy(); 
 
    enhancer enhancer = new enhancer(); 
    enhancer.setsuperclass(userserviceimpl.class); 
    enhancer.setcallback(cglibproxy); 
 
    userservice o = (userservice)enhancer.create(); 
    o.getname(1); 
    o.getage(1); 
  } 
} 

运行结果:

++++++before cglib$getname$0++++++
getname
------getname------
++++++before cglib$getname$0++++++
++++++before cglib$getage$1++++++
getage
------getage------
++++++before cglib$getage$1++++++

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!