目录:
- 简介
- jdk动态代理
- cglib动态代理
- jdk动态代理与cglib的区别
- 应用spring的aop
简介
动态代理是在不修改原有代码的基础上动态增强类的职责,两种实现方式,一种是jdk自带或cglib中实现的,主要应用有spring aop、记录日志、事物管理等。
jdk动态代理
jdk动态代理是基于java的反射机制动态生成代理类从而实现代理。
要求:被代理类实现接口
例子:
public interface Subject {
public void helloWorld();
}
public class RealSubject implements Subject{
@Override
public void helloWorld() {
System.out.println("say hello to the world");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyHandler implements InvocationHandler{
private Object target;
public MyHandler(Object obj){
this.target = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("do something before");
method.invoke(target, args);
System.out.println("do something after");
return null;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
RealSubject realsub = new RealSubject();
InvocationHandler handler = new MyHandler(realsub);
Subject sub = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
RealSubject.class.getInterfaces(), handler);
sub.helloWorld();
}
}
网上找到反编译后的$Proxy0
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Subject{
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;
static {
try {
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]);
m3 = Class.forName("Subject").getMethod("helloWorld",
new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString",
new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
}
@Override
public final boolean equals(Object obj) {
try {
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
.booleanValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void helloWorld() {
try {
super.h.invoke(this, m3, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
cglib动态代理
使用cglib[Code Generation Library]实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码。
核心:通过继承实现代理
例子:
public class RealSubject {
public void helloWorld() {
System.out.println("say hello to the world");
}
}
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 CglibProxy implements MethodInterceptor{
public Object createProxy(Class clazz){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println("do before ");
Object result = methodProxy.invokeSuper(obj, args);
System.out.println("do after ");
return result;
}
}
import net.sf.cglib.core.DebuggingClassWriter;
public class Client {
public static void main(String[] args) {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "G:\\code");
CglibProxy proxy = new CglibProxy();
RealSubject proxySubject = (RealSubject) proxy.createProxy(RealSubject.class);
proxySubject.helloWorld();
}
}
RealSubject$$EnhancerByCGLIB$$8f2454c.class
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class RealSubject$$EnhancerByCGLIB$$8f2454c extends RealSubject
implements Factory
{
private boolean CGLIB$BOUND;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static final Method CGLIB$helloWorld$0$Method;
private static final MethodProxy CGLIB$helloWorld$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$finalize$1$Method;
private static final MethodProxy CGLIB$finalize$1$Proxy;
private static final Method CGLIB$equals$2$Method;
private static final MethodProxy CGLIB$equals$2$Proxy;
private static final Method CGLIB$toString$3$Method;
private static final MethodProxy CGLIB$toString$3$Proxy;
private static final Method CGLIB$hashCode$4$Method;
private static final MethodProxy CGLIB$hashCode$4$Proxy;
private static final Method CGLIB$clone$5$Method;
private static final MethodProxy CGLIB$clone$5$Proxy;
static void CGLIB$STATICHOOK1()
{
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class localClass1 = Class.forName("cglib.RealSubject$$EnhancerByCGLIB$$8f2454c");
Class localClass2;
Method[] tmp50_47 = ReflectUtils.findMethods(new String[] { "helloWorld", "()V" }, (localClass2 = Class.forName("cglib.RealSubject")).getDeclaredMethods());
CGLIB$helloWorld$0$Method = tmp50_47[0];
CGLIB$helloWorld$0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "helloWorld", "CGLIB$helloWorld$0");
tmp50_47;
Method[] tmp143_140 = ReflectUtils.findMethods(new String[] { "finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (localClass2 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$finalize$1$Method = tmp143_140[0];
CGLIB$finalize$1$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "finalize", "CGLIB$finalize$1");
Method[] tmp163_143 = tmp143_140;
CGLIB$equals$2$Method = tmp163_143[1];
CGLIB$equals$2$Proxy = MethodProxy.create(localClass2, localClass1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
Method[] tmp183_163 = tmp163_143;
CGLIB$toString$3$Method = tmp183_163[2];
CGLIB$toString$3$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
Method[] tmp203_183 = tmp183_163;
CGLIB$hashCode$4$Method = tmp203_183[3];
CGLIB$hashCode$4$Proxy = MethodProxy.create(localClass2, localClass1, "()I", "hashCode", "CGLIB$hashCode$4");
Method[] tmp223_203 = tmp203_183;
CGLIB$clone$5$Method = tmp223_203[4];
CGLIB$clone$5$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
tmp223_203;
return;
}
final void CGLIB$helloWorld$0()
{
super.helloWorld();
}
public final void helloWorld()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
if (this.CGLIB$CALLBACK_0 != null)
return;
super.helloWorld();
}
final void CGLIB$finalize$1()
throws Throwable
{
super.finalize();
}
protected final void finalize()
throws Throwable
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
if (this.CGLIB$CALLBACK_0 != null)
return;
super.finalize();
}
final boolean CGLIB$equals$2(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$2$Method, new Object[] { paramObject }, CGLIB$equals$2$Proxy);
tmp41_36;
return tmp41_36 == null ? false : ((Boolean)tmp41_36).booleanValue();
}
return super.equals(paramObject);
}
final String CGLIB$toString$3()
{
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$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy);
return super.toString();
}
final int CGLIB$hashCode$4()
{
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$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
tmp36_31;
return tmp36_31 == null ? 0 : ((Number)tmp36_31).intValue();
}
return super.hashCode();
}
final Object CGLIB$clone$5()
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$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy);
return super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature paramSignature)
{
String tmp4_1 = paramSignature.toString();
switch (tmp4_1.hashCode())
{
case -1574182249:
if (tmp4_1.equals("finalize()V"))
return CGLIB$finalize$1$Proxy;
case -508378822:
case 494307733:
case 1826985398:
case 1913648695:
case 1984935277:
}
}
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 cglib/RealSubject$$EnhancerByCGLIB$$8f2454c
// 4: astore_1
// 5: aload_1
// 6: getfield 198 cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$BOUND Z
// 9: ifne +43 -> 52
// 12: aload_1
// 13: iconst_1
// 14: putfield 198 cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$BOUND Z
// 17: getstatic 24 cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$THREAD_CALLBACKS Ljava/lang/ThreadLocal;
// 20: invokevirtual 201 java/lang/ThreadLocal:get ()Ljava/lang/Object;
// 23: dup
// 24: ifnonnull +15 -> 39
// 27: pop
// 28: getstatic 196 cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$STATIC_CALLBACKS [Lnet/sf/cglib/proxy/Callback;
// 31: dup
// 32: ifnonnull +7 -> 39
// 35: pop
// 36: goto +16 -> 52
// 39: checkcast 202 [Lnet/sf/cglib/proxy/Callback;
// 42: aload_1
// 43: swap
// 44: iconst_0
// 45: aaload
// 46: checkcast 48 net/sf/cglib/proxy/MethodInterceptor
// 49: putfield 36 cglib/RealSubject$$EnhancerByCGLIB$$8f2454c: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 8f2454c();
}
public Object newInstance(Callback paramCallback)
{
CGLIB$SET_THREAD_CALLBACKS(new Callback[] { paramCallback });
CGLIB$SET_THREAD_CALLBACKS(null);
return new 8f2454c();
}
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 8f2454c();
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();
}
}
jdk动态代理与cglib的区别
JDK动态代理
优点
不依赖第三方jar包, 使用方便
随着JDK的升级,JDK动态代理的性能在稳步提升
缺点
只能代理实现了接口的类
执行速度较慢
适用场景
如果你的程序需要频繁、反复地创建代理对象,则JDK动态代理在性能上更占优。
cglib
优点
由于是动态生成字节码实现代理,因此代理对象的执行速度较快, 约为JDK动态代理的1.5 ~ 2倍
可以代理没有实现接口的对象
缺点
不能代理final
类
动态生成字节码虽然执行较快,但是生成速度很慢,根据网上一些人的测试结果,cglib创建代理对象的速度要比JDK慢10 ~ 15倍。
适用场景
不需要频繁创建代理对象的应用,如spring中默认的单例bean,只需要在容器启动时生成一次代理对象。
应用 spring aop
被代理的类如果有实现的接口 优先使用jdk动态代理,否则用cglib动态代理。