Java 动态代理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 动态代理相关的知识,希望对你有一定的参考价值。
一、动态代理的由来
代理是指:给每个具体类写一个代理类,以后要使用某个具体的类时,只要创建它的代理类的对象,然后调用代理类的方法就可以了,可是如果现在有很多具体的类,那就需要创建很多的代理类才可以,这样显然很不合适,那动态代理就应运而生。
二、Java实现动态代理有2种方式:
1、JDK实现动态代理,但是它需要实现类通过接口定义业务方法,对于没有接口的类是无法实现的;
2、CGLib,它采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用。
JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
三、JDK的实现
此类型的动态代理使用到了一个接口InvocationHandler和一个代理类Proxy,这两个类配合使用即可实现动态代理。
//接口 interface InterfaceClass { void show() ; } //具体实现类A class ClassA implements InterfaceClass { @Override public void show(){ System.out.println("class A") ; } } //具体实现类B class ClassB implements InterfaceClass { @Override public void show(){ System.out.println("class B") ; } } //动态代理类,实现InvocationHandler接口 class Invoker implements InvocationHandler { InterfaceClass ia ; public Invoker(InterfaceClass ia) { this.ia = ia ; } @Override public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable { method.invoke(ia, arg) ; return null ; } } // Test class DynamicProxyTest{ public static void main(String[] args){ // 创建具体类ClassA的处理对象 Invoker invoker1 = new Invoker(new ClassA()); // 获得具体类ClassA的代理 InterfaceClass ic1 = (InterfaceClass)Proxy.newProxyInstance(InterfaceClass.class.getClassLoader(), new Class[]{InterfaceClass.class}, invoker1); ic1.show() ; // classB也是如此 } }
四、CGLib实现
public class CGLIBProxy implements MethodInterceptor{ private Enhancer enhancer = new Enhancer() ; public Object getProxy(Class clazz) { // 设置父类 enhancer.setSuperclass(clazz); enhancer.setCallback(this); // 通过字节码技术动态创建子类实力 return enhancer.create() ; } // 所有的方法都会被这个方法所拦截,该类实现了子类的方法与代理的方法。getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class类创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,args为方法动态入参,proxy为代理类实例。 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodproxy) throws Throwable{ Object result = methodproxy.invokerSuper(obj, args) ; return result ; } } public class UserServiceImpl{ public void sayHello() { System.out.println("sayHello method") ; } public void sayBye() { System.out.println("sayBye method") ; } } // Test public class Test{ public static void main(String[] args) { CGLIBProxy proxy = new CGLIBProxy() ; UserServiceImpl impl = (UserServiceImpl)proxy.getProxy(UserServiceImpl.class) ; impl.sayHello() ; } }
六、比较两种方式的优缺点
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib更合适,反之使用JDK方式要更好些。同时,用于CGLib采用的动态代理创建子类的方式,对于final方法,无法进行处理。
以上是关于Java 动态代理的主要内容,如果未能解决你的问题,请参考以下文章