前言:

这2种动态代理算是老生常谈的吧,面试还是会经常问到的,下面做下分析:

jdk动态代理:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class JdkHanler implements InvocationHandler { private Object target; public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable {
System.out.println("before");
Object o=method.invoke(target, arg);
System.out.println("after");
return o;
}
public JdkHanler(Object target) {
super();
this.target = target;
}
public Object getInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}

cglib动态代理:

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; public class HelloWorldInterceptor implements MethodInterceptor { private Object target; public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before");
Object r=proxy.invokeSuper(obj, args);
System.out.println("after");
return r;
}
public HelloWorldInterceptor(Object target) {
super();
this.target = target;
}
public Object getInstance(){
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
}

测试类:

public class AllTest {

    public static final String output="D:/SpringWorkSpace/";
//cglib生成代理类字节码文件
static{
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, output);
} @Test
public void proxyTest(){
HelloWorldInterceptor interceptor=new HelloWorldInterceptor(new HelloWorldImpl());
HelloWorld h=(HelloWorld) interceptor.getInstance();
h.sayHello();
}
//@Test
public void jdkproxyTest() throws IOException{
JdkHanler hanler=new JdkHanler(new HelloWorldImpl());
HelloWorld h=(HelloWorld) hanler.getInstance();
h.sayHello();
jdkToFile(h);
}
//jdk代理类字节码文件
public static void jdkToFile(HelloWorld obj) throws IOException {
Class clazz = obj.getClass();
String className = clazz.getName();
byte[] classFile = ProxyGenerator.generateProxyClass(className, HelloWorldImpl.class.getInterfaces());
FileOutputStream fos = new FileOutputStream(output+"proxy.class");
fos.write(classFile);
}
}

利用jd-gui工具反编译字节码文件:

生成的jdk代理类:

public final class $Proxy4 extends Proxy
implements HelloWorld
{
private static Method m3;
private static Method m1;
private static Method m0;
private static Method m2; public $Proxy4(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
//调用sayHello方法
public final String sayHello()
throws
{
try
{
//调用JdkHanler的invoke方法
return (String)this.h.invoke(this, m3, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} static
{
try
{
m3 = Class.forName("com.selrain.DynamicProxy.HelloWorld").getMethod("sayHello", new Class[0]);
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}

生成的cglib代理类:

public class HelloWorld$$EnhancerByCGLIB$$d87b5f2a extends HelloWorld
implements Factory
{
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$sayHello$0$Method;
private static final MethodProxy CGLIB$sayHello$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$hashCode$1$Method;
private static final MethodProxy CGLIB$hashCode$1$Proxy;
private static final Method CGLIB$clone$2$Method;
private static final MethodProxy CGLIB$clone$2$Proxy;
private static final Method CGLIB$equals$3$Method;
private static final MethodProxy CGLIB$equals$3$Proxy;
private static final Method CGLIB$toString$4$Method;
private static final MethodProxy CGLIB$toString$4$Proxy; static void CGLIB$STATICHOOK1()
{
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class localClass1 = Class.forName("com.selrain.DynamicProxy.HelloWorld$$EnhancerByCGLIB$$d87b5f2a");
Class localClass2;
Method[] tmp50_47 = ReflectUtils.findMethods(new String[] { "sayHello", "()Ljava/lang/String;" }, (localClass2 = Class.forName("com.selrain.DynamicProxy.HelloWorld")).getDeclaredMethods());
CGLIB$sayHello$0$Method = tmp50_47[0];
CGLIB$sayHello$0$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/String;", "sayHello", "CGLIB$sayHello$0");
tmp50_47;
Method[] tmp131_128 = ReflectUtils.findMethods(new String[] { "hashCode", "()I", "clone", "()Ljava/lang/Object;", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;" }, (localClass2 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$hashCode$1$Method = tmp131_128[0];
CGLIB$hashCode$1$Proxy = MethodProxy.create(localClass2, localClass1, "()I", "hashCode", "CGLIB$hashCode$1");
Method[] tmp151_131 = tmp131_128;
CGLIB$clone$2$Method = tmp151_131[1];
CGLIB$clone$2$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$2");
Method[] tmp171_151 = tmp151_131;
CGLIB$equals$3$Method = tmp171_151[2];
CGLIB$equals$3$Proxy = MethodProxy.create(localClass2, localClass1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$3");
Method[] tmp191_171 = tmp171_151;
CGLIB$toString$4$Method = tmp191_171[3];
CGLIB$toString$4$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/String;", "toString", "CGLIB$toString$4");
tmp191_171;
} final String CGLIB$sayHello$0()
{
return super.sayHello();
}
//调用sayHello方法
public final String sayHello()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null)
//HelloWorldInterceptor 的intercept 方法
return (String)tmp17_14.intercept(this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
return super.sayHello();
} final int CGLIB$hashCode$1()
{
return super.hashCode();
} public final int hashCode()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null)
{
Object tmp36_31 = tmp17_14.intercept(this, CGLIB$hashCode$1$Method, CGLIB$emptyArgs, CGLIB$hashCode$1$Proxy);
tmp36_31;
return tmp36_31 == null ? 0 : ((Number)tmp36_31).intValue();
}
return super.hashCode();
} final Object CGLIB$clone$2()
throws CloneNotSupportedException
{
return super.clone();
} protected final Object clone()
throws CloneNotSupportedException
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null)
return tmp17_14.intercept(this, CGLIB$clone$2$Method, CGLIB$emptyArgs, CGLIB$clone$2$Proxy);
return super.clone();
} final boolean CGLIB$equals$3(Object paramObject)
{
return super.equals(paramObject);
} public final boolean equals(Object paramObject)
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null)
{
Object tmp41_36 = tmp17_14.intercept(this, CGLIB$equals$3$Method, new Object[] { paramObject }, CGLIB$equals$3$Proxy);
tmp41_36;
return tmp41_36 == null ? false : ((Boolean)tmp41_36).booleanValue();
}
return super.equals(paramObject);
} final String CGLIB$toString$4()
{
return super.toString();
} public final String toString()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null)
return (String)tmp17_14.intercept(this, CGLIB$toString$4$Method, CGLIB$emptyArgs, CGLIB$toString$4$Proxy);
return super.toString();
} public static MethodProxy CGLIB$findMethodProxy(Signature paramSignature)
{
String tmp4_1 = paramSignature.toString();
switch (tmp4_1.hashCode())
{
case -508378822:
if (tmp4_1.equals("clone()Ljava/lang/Object;"))
return CGLIB$clone$2$Proxy;
break;
case 1459740658:
case 1826985398:
case 1913648695:
case 1984935277:
}
} public HelloWorld$$EnhancerByCGLIB$$d87b5f2a()
{
CGLIB$BIND_CALLBACKS(this);
} public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback)
{
CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
} public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback)
{
CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
} private static final void CGLIB$BIND_CALLBACKS(Object paramObject)
{
// Byte code:
// 0: aload_0
// 1: checkcast 2 com/selrain/DynamicProxy/HelloWorld$$EnhancerByCGLIB$$d87b5f2a
// 4: astore_1
// 5: aload_1
// 6: getfield 186 com/selrain/DynamicProxy/HelloWorld$$EnhancerByCGLIB$$d87b5f2a:CGLIB$BOUND Z
// 9: ifne +43 -> 52
// 12: aload_1
// 13: iconst_1
// 14: putfield 186 com/selrain/DynamicProxy/HelloWorld$$EnhancerByCGLIB$$d87b5f2a:CGLIB$BOUND Z
// 17: getstatic 27 com/selrain/DynamicProxy/HelloWorld$$EnhancerByCGLIB$$d87b5f2a:CGLIB$THREAD_CALLBACKS Ljava/lang/ThreadLocal;
// 20: invokevirtual 189 java/lang/ThreadLocal:get ()Ljava/lang/Object;
// 23: dup
// 24: ifnonnull +15 -> 39
// 27: pop
// 28: getstatic 184 com/selrain/DynamicProxy/HelloWorld$$EnhancerByCGLIB$$d87b5f2a:CGLIB$STATIC_CALLBACKS [Lnet/sf/cglib/proxy/Callback;
// 31: dup
// 32: ifnonnull +7 -> 39
// 35: pop
// 36: goto +16 -> 52
// 39: checkcast 190 [Lnet/sf/cglib/proxy/Callback;
// 42: aload_1
// 43: swap
// 44: iconst_0
// 45: aaload
// 46: checkcast 52 net/sf/cglib/proxy/MethodInterceptor
// 49: putfield 40 com/selrain/DynamicProxy/HelloWorld$$EnhancerByCGLIB$$d87b5f2a:CGLIB$CALLBACK_0 Lnet/sf/cglib/proxy/MethodInterceptor;
// 52: return
} public Object newInstance(Callback[] paramArrayOfCallback)
{
CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
CGLIB$SET_THREAD_CALLBACKS(null);
return new d87b5f2a();
} public Object newInstance(Callback paramCallback)
{
CGLIB$SET_THREAD_CALLBACKS(new Callback[] { paramCallback });
CGLIB$SET_THREAD_CALLBACKS(null);
return new d87b5f2a();
} public Object newInstance(Class[] paramArrayOfClass, Object[] paramArrayOfObject, Callback[] paramArrayOfCallback)
{
CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
Class[] tmp9_8 = paramArrayOfClass;
switch (tmp9_8.length)
{
case 0:
tmp9_8;
break;
default:
new d87b5f2a();
throw new IllegalArgumentException("Constructor not found");
}
CGLIB$SET_THREAD_CALLBACKS(null);
} public Callback getCallback(int paramInt)
{
CGLIB$BIND_CALLBACKS(this);
switch (paramInt)
{
case 0:
break;
}
return null;
} public void setCallback(int paramInt, Callback paramCallback)
{
switch (paramInt)
{
case 0:
this.CGLIB$CALLBACK_0 = ((MethodInterceptor)paramCallback);
break;
}
} public Callback[] getCallbacks()
{
CGLIB$BIND_CALLBACKS(this);
return new Callback[] { this.CGLIB$CALLBACK_0 };
} public void setCallbacks(Callback[] paramArrayOfCallback)
{
this.CGLIB$CALLBACK_0 = ((MethodInterceptor)paramArrayOfCallback[0]);
} static
{
CGLIB$STATICHOOK1();
}
}

MethodProxy 的invokeSuper方法:

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
//调用代理类的CGLIB$sayHello$0方法
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
//生成fastClass类:其中f1代表target,(其type属性为target),f2代表生成的代理类;i1和i2分别代表方法sayHello和CGLIB$sayHello$0方法对应的索引位置
private void init()
{
if (fastClassInfo == null)
{
synchronized (initLock)
{
if (fastClassInfo == null)
{
CreateInfo ci = createInfo; FastClassInfo fci = new FastClassInfo();
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
fci.i1 = fci.f1.getIndex(sig1);
fci.i2 = fci.f2.getIndex(sig2);
fastClassInfo = fci;
createInfo = null;
}
}
}
}

代理类的CGLIB$sayHello$0方法:

final String CGLIB$sayHello$0()
{
//最终调用target的sayHello方法
return super.sayHello();
}

区别:

1、jdk动态代理生成的代理类和委托类实现了相同的接口

2、jdk动态代理利用了Java的反射机制,cglib动态代理利用了索引的方式直接调用委托类的方法,效率更高

参考:

1、占小狼的博客-说说cglib动态代理

2、饿了么物流技术-动态代理的实现与案例

Jdk动态代理和CGLIB动态代理大比拼的更多相关文章

  1. JDK动态代理和CGLib动态代理简单演示

    JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期间创建接口的代理实例. 一.首先我们进行JDK动态代理的演示. 现在我们有一个简单的业务接口Saying,如下: package te ...

  2. 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  3. Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...

  4. Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  5. java的静态代理、jdk动态代理和cglib动态代理

    Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...

  6. jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)

    代理模式是一种很常见的模式,本文主要分析cglib动态代理的过程 1. 举例 使用cglib代理需要引入两个包,maven的话包引入如下 <!-- https://mvnrepository.c ...

  7. 代理模式之静态代理,JDK动态代理和cglib动态代理

    代理模式,顾名思义,就是通过代理去完成某些功能.比如,你需要购买火车票,不想跑那么远到火车站售票窗口买,可以去附近的火车票代售点买,或者到携程等第三方网站买.这个时候,我们就把火车站叫做目标对象或者委 ...

  8. jdk动态代理和cglib动态代理的区别

    一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...

  9. jdk 动态代理和 cglib 动态代理

    原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件加载 ...

  10. 动态代理:jdk动态代理和cglib动态代理

    /** * 动态代理类:先参考代理模式随笔,了解代理模式的概念,分为jdk动态代理和cglib,jdk动态代理是通过实现接口的方式创建代理类的,cglib是通过继承类的方式实现的代理类的 * jdk动 ...

随机推荐

  1. UVa 12709 && UVaLive 6650 Falling Ants (水题)

    题意:给定 n 个长方体的长,宽,高,让你求高最大的时候体积最大是多少. 析:排序,用高和体积排序就好. 代码如下: #pragma comment(linker, "/STACK:1024 ...

  2. 关于kindle无法连接上wifi的问题

    家里换了宽带以后我发现kindle无法链接上WiFi了. 原因可能是我家使用的WiFi网络是1-11之间的信道,也有可能是运营商的问题(由于我是软件开发,对硬件和网络并不是很清楚,只能大概估计一下). ...

  3. (5)css盒子模型(基础上)

    CSS 盒子模型概述 ***什么是CSS的盒子模型呢?为什么叫它是盒子?先说说我们在网页设计中常听的属性名:内容(content).边框(border).内边距(padding).外边距(margin ...

  4. python代码覆盖率coverage简介与用法

    如果衡量单元测试对相应代码的测试重量,覆盖率是一个必要非充分条件,因此统计代码的覆盖率,检视单测是否充分,就尤为的重要.这里针对python-unittest的单测的覆盖率coverage进行使用说明 ...

  5. spring boot 项目发布运行

    1. maven install 发布jar包 2. java -jar webservice.jar 启动jar包

  6. 实验 - cut的应用

    题目一: 1.1 创建一个通讯录 vi phone.txt #进行编辑 cat phone.txt #查看内容 2.1 取出手机号码 cut -f phone.txt 3.1 取出手机前三位 cut ...

  7. 题解报告:hdu 1230 火星A+B(字符串)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1230 Problem Description 读入两个不超过25位的火星正整数A和B,计算A+B.需要 ...

  8. 题解报告:hdu 1229 还是A+B

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1229 Problem Description 读入两个小于10000的正整数A和B,计算A+B.需要注 ...

  9. foreach的学习使用归纳

    1: 实现对双向链表的遍历使用 LinkedList<string> llary = new LinkedList<string>(); llary.AddLast (&quo ...

  10. 分享一款强大的图片查看器插件,手机PC 通吃,功能超级齐全!

    一款强大的图片查看器插件,手机PC 通吃,功能超级齐全! 地址:http://photoswipe.com/