java动态代理实现Proxy和InvocationHandler cglib

来源:互联网 发布:t95e6数据 编辑:程序博客网 时间:2024/05/18 12:39




概念:

静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 
动态代理:在程序运行时,运用反射机制动态创建而成。


JDK的动态代理用起来非常简单,当它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么办?现在我们可以使用CGLIB包。



JDK动态代理实现

import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.Collection;public class ProxyTest {    static StringBuilder sBuilder=new StringBuilder();    public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {                //代理类字节码Class clazzProxy1=    Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);//代理类构造方法列表,没有无参构造方法System.out.println("...........begin constructors list............");    Constructor[] constructors= clazzProxy1.getConstructors();     for(Constructor constructor:constructors){         StringBuilder sBuilder=new StringBuilder();        sBuilder.append(constructor.getName()).append("(");        Class[] clazzparams =constructor.getParameterTypes();            for(Class clazzparam:clazzparams){                        sBuilder.append(clazzparam.getName()).append(",");                    }                if(clazzparams.length!=0){                        sBuilder.deleteCharAt(sBuilder.length()-1);        }        sBuilder.append(")");        System.out.println( sBuilder.toString());     }        //代理类方法列表    System.out.println("...........begin methods list............");         Method[] methods= clazzProxy1.getMethods();     for(Method method:methods){         StringBuilder sBuilder=new StringBuilder();        sBuilder.append(method.getName()).append("(");        Class[] clazzparams =method.getParameterTypes();            for(Class clazzparam:clazzparams){                        sBuilder.append(clazzparam.getName()).append(",");                    }                if(clazzparams.length!=0){                        sBuilder.deleteCharAt(sBuilder.length()-1);        }        sBuilder.append(")");        System.out.println( sBuilder.toString());     }          //通过字节码创建代理类的实例,不能用newInstance(),构造方法传入InvocationHandler     System.out.println("...........begin create instance object............");            Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);            Collection proxy1=    (Collection) constructor.newInstance(new InvocationHandler(){            @Override            public Object invoke(Object proxy, Method method, Object[] args)                    throws Throwable {                                return null;            }                    });            System.out.println(proxy1);    proxy1.clear();//无返回值的方法成功    //一步到位创建代理类实例    Collection proxy2=(Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),new Class[]{Collection.class}, new InvocationHandler(){        ArrayList target=new ArrayList<>();//被代理对象,目标对象        @Override        public Object invoke(Object proxy, Method method, Object[] args)                throws Throwable {                        long begintime=System.currentTimeMillis();            Object retVal=method.invoke(target, args);            long endtime=System.currentTimeMillis();            System.out.println(method.getName()+" running time is " +(endtime-begintime));            return retVal;        }            });        proxy2.add("lhm");    proxy2.add("zxx");    proxy2.add("bxd");    System.out.println(proxy2.size());    System.out.println(proxy2.getClass().getName());    }                    }


CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,

主要是对指定的类生成一个子类覆盖其中的所有方法,所以该类或方法不能声明称final的。


spring中Aspect动态代理设置

Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。

默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。

如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。


本文出自 “点滴积累” 博客,请务必保留此出处http://tianxingzhe.blog.51cto.com/3390077/1719600

0 0
原创粉丝点击