概念:java
静态代理:由程序员建立或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态建立而成。
程序员
JDK的动态代理用起来很是简单,当它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。若是想代理没有实现接口的继承的类,该怎么办?如今咱们能够使用CGLIB包。spring
JDK动态代理实现
app
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)代理是针对类实现代理,ide
主要是对指定的类生成一个子类,覆盖其中的全部方法,因此该类或方法不能声明称final的。工具
spring中Aspect动态代理设置
ui
Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪一种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。spa
默认的策略是若是目标类是接口,则使用JDK动态代理技术,若是目标对象没有实现接口,则默认会采用CGLIB代理。代理
若是目标对象实现了接口,能够强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。对象