1 jdk动态代理
jdk动态代理限制:只能对实现了某一个接口的类进行代理。
原理:生成的代理类也实现了被代理类实现的接口,并且继承了Proxy类
jdk提供动态代理的工具:接口:java.lang.reflect.InvocationHandler, java.lang.reflect.Proxy;
实现jdk动态代理步骤:
首先定义被代理的类及被代理类实现的接口:
interface Movable {
public void move();
}
class Car implements Movable {
public void move () {
System.out.println("car is moving...");
}
}
定义自己的InvocationHandler
abstract class CarInvocationHandler implements InvocationHandler {
private Movable movable;
CarInvocationHandler(Movable movable) {
this.movable = movable;
}
public Movable getProxyInstance() {
return (Movable)Proxy.newProxyInstance(Movable.class.getClassLoader(), new Class[]{Movable.class}, this);
}
public Class getProxyClass() {
return Proxy.getProxyClass(Movable.class.getClassLoader(), new Class[]{});
}
@Override
public abstract Object invoke(Object proxy, Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
public Movable getMovalbe() {
return this.movable;
}
}
class CarTimeInvocationHandler extends CarInvocationHandler {
CarTimeInvocationHandler(Movable movable) {
super(movable);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
System.out.println("startTime: " + System.currentTimeMillis());
Object result = method.invoke(this.getMovalbe(), args);
System.out.println("end: " + System.currentTimeMillis());
return result;
}
}
实现InvocationHandler时,进行了少量封装,方便实现多种代理的InvocationHandler
获取代理类:调用invocationHanlder的getProxyInstance()方法;想要获取代理类的类可以调用getProxyClass()方法
jdk动态代理原理:
Proxy.newProxyInstance()源码为
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
/*
* Look up or generate the designated proxy class.
*/
Class cl = getProxyClass(loader, interfaces);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
Constructor cons = cl.getConstructor(constructorParams);
return (Object) cons.newInstance(new Object[] { h });
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
} catch (IllegalAccessException e) {
throw new InternalError(e.toString());
} catch (InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
throw new InternalError(e.toString());
}
}
由上图源码可知:Proxy首先获取到被代理类的class:Class cl = getProxyClass(loader, interfaces); 然后根据Class得到代理类的构造函数,然后根据构造函数生成代理类示例,也就是使用了反射。
那么Proxy怎么获取代理类的Class呢?下面是Proxy getProxyClass主要源码:
private byte[] generateClassFile() {
/* ============================================================
* Step 1: Assemble ProxyMethod objects for all methods to
* generate proxy dispatching code for.
*/
/*
* Record that proxy methods are needed for the hashCode, equals,
* and toString methods of java.lang.Object. This is done before
* the methods from the proxy interfaces so that the methods from
* java.lang.Object take precedence over duplicate methods in the
* proxy interfaces.
*/
addProxyMethod(hashCodeMethod, Object.class);
addProxyMethod(equalsMethod, Object.class);
addProxyMethod(toStringMethod, Object.class);
/*
* Now record all of the methods from the proxy interfaces, giving
* earlier interfaces precedence over later ones with duplicate
* methods.
*/
for (int i = 0; i < interfaces.length; i++) {
Method[] methods = interfaces[i].getMethods();
for (int j = 0; j < methods.length; j++) {
addProxyMethod(methods[j], interfaces[i]);
}
}
/*
* For each set of proxy methods with the same signature,
* verify that the methods' return types are compatible.
*/
for (List sigmethods : proxyMethods.values()) {
checkReturnTypes(sigmethods);
}
/* ============================================================
* Step 2: Assemble FieldInfo and MethodInfo structs for all of
* fields and methods in the class we are generating.
*/
try {
methods.add(generateConstructor());
for (List sigmethods : proxyMethods.values()) {
for (ProxyMethod pm : sigmethods) {
// add static field for method's Method object
fields.add(new FieldInfo(pm.methodFieldName,
"Ljava/lang/reflect/Method;",
ACC_PRIVATE | ACC_STATIC));
// generate code for proxy method and add it
methods.add(pm.generateMethod());
}
}
methods.add(generateStaticInitializer());
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
if (methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
}
if (fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
}
/* ============================================================
* Step 3: Write the final class file.
*/
/*
* Make sure that constant pool indexes are reserved for the
* following items before starting to write the final class file.
*/
cp.getClass(dotToSlash(className));
cp.getClass(superclassName);
for (int i = 0; i < interfaces.length; i++) {
cp.getClass(dotToSlash(interfaces[i].getName()));
}
/*
* Disallow new constant pool additions beyond this point, since
* we are about to write the final constant pool table.
*/
cp.setReadOnly();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
try {
/*
* Write all the items of the "ClassFile" structure.
* See JVMS section 4.1.
*/
// u4 magic;
dout.writeInt(0xCAFEBABE);
// u2 minor_version;
dout.writeShort(CLASSFILE_MINOR_VERSION);
// u2 major_version;
dout.writeShort(CLASSFILE_MAJOR_VERSION);
cp.write(dout); // (write constant pool)
// u2 access_flags;
dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
// u2 this_class;
dout.writeShort(cp.getClass(dotToSlash(className)));
// u2 super_class;
dout.writeShort(cp.getClass(superclassName));
// u2 interfaces_count;
dout.writeShort(interfaces.length);
// u2 interfaces[interfaces_count];
for (int i = 0; i < interfaces.length; i++) {
dout.writeShort(cp.getClass(
dotToSlash(interfaces[i].getName())));
}
// u2 fields_count;
dout.writeShort(fields.size());
// field_info fields[fields_count];
for (FieldInfo f : fields) {
f.write(dout);
}
// u2 methods_count;
dout.writeShort(methods.size());
// method_info methods[methods_count];
for (MethodInfo m : methods) {
m.write(dout);
}
// u2 attributes_count;
dout.writeShort(0); // (no ClassFile attributes for proxy classes)
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
return bout.toByteArray();
}
由上可知:首先生成成员变量,代理方法,然后做一定的检查,然后返回字节码。
以下是生成代理类的代码:
import com.malone.proxy.Movable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class Proxy11 extends Proxy
implements Movable
{
private static Method m1;
private static Method m3;
private static Method m0;
private static Method m2;
public Proxy11(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void move()
throws
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return ((String)this.h.invoke(this, m2, null));
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("com.malone.proxy.Movable").getMethod("move", new Class[0]);
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());
}
}
}
由生成代理类的代码可知,代理类实现了被代理类实现的接口,继承了Proxy类,代理类的构造函数会把参赛handler赋给Proxy类的handler,根据代理类创建代理类对象时,
Constructor cons = cl.getConstructor(constructorParams);
return (Object) cons.newInstance(new Object[] { h });
Proxy.newInstance()方法中传递的handler传递到代理类的构造函数里,及赋给了Proxy的handler。
当代理类调用equals,hashCode, toString,和代理类实现接口中的方法时,实际上执行的是自己定义的invocationHanlder的invoke方法。
jdk生成代理时,我们很难找到代理类的class文件
利用下面一个工具方法可以指定生成class文件路径:
class ProxyGeneratorUtils {
/**
* 把代理类的字节码写到硬盘上
* @param path 保存路径
*/
public static void writeProxyClassToHardDisk(String path) {
// 第一种方法,这种方式在刚才分析ProxyGenerator时已经知道了
// System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true);
// 第二种方法
// 获取代理类的字节码
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", Car.class.getInterfaces());
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
二 cglib动态代理
限制:cglib不能代理类的final方法
原理:cglib通过操作asm,给被代理类生成子类
和jdk动态代理比较:不需要实现接口
cglib生成动态代理类的主要代码:
//被代理类
class TargetClass {
public void create() {
System.out.println("create method...");
}
public void update() {
System.out.println("update method...");
}
}
代理实现类
class CglibProxy implements MethodInterceptor {
private Enhancer enhance = new Enhancer();
public Object getProxyInstance(Class clazz) {
enhance.setSuperclass(clazz);
enhance.setCallback(this);
enhance.setCallbackFilter(new MyCallbackFilter());
enhance.setCallbacks(new Callback[]{new CglibProxy(), new MyFixedValue()});
return enhance.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("prefix operate...");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after operate...");
return result;
}
}
生成代理类代码:
// Decompiled by DJ v3.7.7.81 Copyright 2004 Atanas Neshkov Date: 2013/10/24 11:19:09
// Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version!
// Decompiler options: packimports(3)
// Source File Name:
package com.malone.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.*;
// Referenced classes of package com.malone.proxy:
// TargetClass
public class TargetClass$$EnhancerByCGLIB$$a0f953e6 extends TargetClass
implements Factory
{
static void CGLIB$STATICHOOK1()
{
Class class1;
ClassLoader classloader;
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
classloader = (class1 = Class.forName("com.malone.proxy.TargetClass$$EnhancerByCGLIB$$a0f953e6")).getClassLoader();
classloader;
CGLIB$emptyArgs = new Object[0];
CGLIB$create$0$Proxy = MethodProxy.create(classloader, (CGLIB$create$0$Method = Class.forName("com.malone.proxy.TargetClass").getDeclaredMethod("create", new Class[0])).getDeclaringClass(), class1, "()V", "create", "CGLIB$create$0");
CGLIB$update$1$Proxy = MethodProxy.create(classloader, (CGLIB$update$1$Method = Class.forName("com.malone.proxy.TargetClass").getDeclaredMethod("update", new Class[0])).getDeclaringClass(), class1, "()V", "update", "CGLIB$update$1");
CGLIB$finalize$2$Proxy = MethodProxy.create(classloader, (CGLIB$finalize$2$Method = Class.forName("java.lang.Object").getDeclaredMethod("finalize", new Class[0])).getDeclaringClass(), class1, "()V", "finalize", "CGLIB$finalize$2");
CGLIB$hashCode$3$Proxy = MethodProxy.create(classloader, (CGLIB$hashCode$3$Method = Class.forName("java.lang.Object").getDeclaredMethod("hashCode", new Class[0])).getDeclaringClass(), class1, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Proxy = MethodProxy.create(classloader, (CGLIB$clone$4$Method = Class.forName("java.lang.Object").getDeclaredMethod("clone", new Class[0])).getDeclaringClass(), class1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
CGLIB$equals$5$Proxy = MethodProxy.create(classloader, (CGLIB$equals$5$Method = Class.forName("java.lang.Object").getDeclaredMethod("equals", new Class[] {
Class.forName("java.lang.Object")
})).getDeclaringClass(), class1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$5");
CGLIB$toString$6$Proxy = MethodProxy.create(classloader, (CGLIB$toString$6$Method = Class.forName("java.lang.Object").getDeclaredMethod("toString", new Class[0])).getDeclaringClass(), class1, "()Ljava/lang/String;", "toString", "CGLIB$toString$6");
return;
}
final void CGLIB$create$0()
{
super.create();
}
public final void create()
{
CGLIB$CALLBACK_0;
if(CGLIB$CALLBACK_0 != null) goto _L2; else goto _L1
_L1:
JVM INSTR pop ;
CGLIB$BIND_CALLBACKS(this);
CGLIB$CALLBACK_0;
_L2:
JVM INSTR dup ;
JVM INSTR ifnull 37;
goto _L3 _L4
_L3:
break MISSING_BLOCK_LABEL_21;
_L4:
break MISSING_BLOCK_LABEL_37;
this;
CGLIB$create$0$Method;
CGLIB$emptyArgs;
CGLIB$create$0$Proxy;
intercept();
return;
super.create();
return;
}
final void CGLIB$update$1()
{
super.update();
}
public final void update()
{
CGLIB$CALLBACK_0;
if(CGLIB$CALLBACK_0 != null) goto _L2; else goto _L1
_L1:
JVM INSTR pop ;
CGLIB$BIND_CALLBACKS(this);
CGLIB$CALLBACK_0;
_L2:
JVM INSTR dup ;
JVM INSTR ifnull 37;
goto _L3 _L4
_L3:
break MISSING_BLOCK_LABEL_21;
_L4:
break MISSING_BLOCK_LABEL_37;
this;
CGLIB$update$1$Method;
CGLIB$emptyArgs;
CGLIB$update$1$Proxy;
intercept();
return;
super.update();
return;
}
final void CGLIB$finalize$2()
throws Throwable
{
super.finalize();
}
protected final void finalize()
throws Throwable
{
CGLIB$CALLBACK_0;
if(CGLIB$CALLBACK_0 != null) goto _L2; else goto _L1
_L1:
JVM INSTR pop ;
CGLIB$BIND_CALLBACKS(this);
CGLIB$CALLBACK_0;
_L2:
JVM INSTR dup ;
JVM INSTR ifnull 37;
goto _L3 _L4
_L3:
break MISSING_BLOCK_LABEL_21;
_L4:
break MISSING_BLOCK_LABEL_37;
this;
CGLIB$finalize$2$Method;
CGLIB$emptyArgs;
CGLIB$finalize$2$Proxy;
intercept();
return;
super.finalize();
return;
}
final int CGLIB$hashCode$3()
{
return super.hashCode();
}
public final int hashCode()
{
CGLIB$CALLBACK_0;
if(CGLIB$CALLBACK_0 != null) goto _L2; else goto _L1
_L1:
JVM INSTR pop ;
CGLIB$BIND_CALLBACKS(this);
CGLIB$CALLBACK_0;
_L2:
JVM INSTR dup ;
JVM INSTR ifnull 52;
goto _L3 _L4
_L3:
this;
CGLIB$hashCode$3$Method;
CGLIB$emptyArgs;
CGLIB$hashCode$3$Proxy;
intercept();
JVM INSTR dup ;
JVM INSTR ifnonnull 45;
goto _L5 _L6
_L5:
JVM INSTR pop ;
0;
goto _L7
_L6:
(Number);
intValue();
_L7:
return;
_L4:
return super.hashCode();
}
final Object CGLIB$clone$4()
throws CloneNotSupportedException
{
return super.clone();
}
protected final Object clone()
throws CloneNotSupportedException
{
CGLIB$CALLBACK_0;
if(CGLIB$CALLBACK_0 != null) goto _L2; else goto _L1
_L1:
JVM INSTR pop ;
CGLIB$BIND_CALLBACKS(this);
CGLIB$CALLBACK_0;
_L2:
JVM INSTR dup ;
JVM INSTR ifnull 37;
goto _L3 _L4
_L3:
this;
CGLIB$clone$4$Method;
CGLIB$emptyArgs;
CGLIB$clone$4$Proxy;
intercept();
return;
_L4:
return super.clone();
}
final boolean CGLIB$equals$5(Object obj)
{
return super.equals(obj);
}
public final boolean equals(Object obj)
{
CGLIB$CALLBACK_0;
if(CGLIB$CALLBACK_0 != null) goto _L2; else goto _L1
_L1:
JVM INSTR pop ;
CGLIB$BIND_CALLBACKS(this);
CGLIB$CALLBACK_0;
_L2:
JVM INSTR dup ;
JVM INSTR ifnull 57;
goto _L3 _L4
_L3:
this;
CGLIB$equals$5$Method;
new Object[] {
obj
};
CGLIB$equals$5$Proxy;
intercept();
JVM INSTR dup ;
JVM INSTR ifnonnull 50;
goto _L5 _L6
_L5:
JVM INSTR pop ;
false;
goto _L7
_L6:
(Boolean);
booleanValue();
_L7:
return;
_L4:
return super.equals(obj);
}
final String CGLIB$toString$6()
{
return super.toString();
}
public final String toString()
{
CGLIB$CALLBACK_0;
if(CGLIB$CALLBACK_0 != null) goto _L2; else goto _L1
_L1:
JVM INSTR pop ;
CGLIB$BIND_CALLBACKS(this);
CGLIB$CALLBACK_0;
_L2:
JVM INSTR dup ;
JVM INSTR ifnull 40;
goto _L3 _L4
_L3:
this;
CGLIB$toString$6$Method;
CGLIB$emptyArgs;
CGLIB$toString$6$Proxy;
intercept();
(String);
return;
_L4:
return super.toString();
}
public static MethodProxy CGLIB$findMethodProxy(Signature signature)
{
String s = signature.toString();
s;
s.hashCode();
JVM INSTR lookupswitch 7: default 160
// -1949253108: 76
// -1574182249: 88
// -508378822: 100
// 598313209: 112
// 1826985398: 124
// 1913648695: 136
// 1984935277: 148;
goto _L1 _L2 _L3 _L4 _L5 _L6 _L7 _L8
_L2:
"update()V";
equals();
JVM INSTR ifeq 161;
goto _L9 _L10
_L10:
break MISSING_BLOCK_LABEL_161;
_L9:
return CGLIB$update$1$Proxy;
_L3:
"finalize()V";
equals();
JVM INSTR ifeq 161;
goto _L11 _L12
_L12:
break MISSING_BLOCK_LABEL_161;
_L11:
return CGLIB$finalize$2$Proxy;
_L4:
"clone()Ljava/lang/Object;";
equals();
JVM INSTR ifeq 161;
goto _L13 _L14
_L14:
break MISSING_BLOCK_LABEL_161;
_L13:
return CGLIB$clone$4$Proxy;
_L5:
"create()V";
equals();
JVM INSTR ifeq 161;
goto _L15 _L16
_L16:
break MISSING_BLOCK_LABEL_161;
_L15:
return CGLIB$create$0$Proxy;
_L6:
"equals(Ljava/lang/Object;)Z";
equals();
JVM INSTR ifeq 161;
goto _L17 _L18
_L18:
break MISSING_BLOCK_LABEL_161;
_L17:
return CGLIB$equals$5$Proxy;
_L7:
"toString()Ljava/lang/String;";
equals();
JVM INSTR ifeq 161;
goto _L19 _L20
_L20:
break MISSING_BLOCK_LABEL_161;
_L19:
return CGLIB$toString$6$Proxy;
_L8:
"hashCode()I";
equals();
JVM INSTR ifeq 161;
goto _L21 _L22
_L22:
break MISSING_BLOCK_LABEL_161;
_L21:
return CGLIB$hashCode$3$Proxy;
_L1:
JVM INSTR pop ;
return null;
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback acallback[])
{
CGLIB$THREAD_CALLBACKS.set(acallback);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback acallback[])
{
CGLIB$STATIC_CALLBACKS = acallback;
}
private static final void CGLIB$BIND_CALLBACKS(Object obj)
{
TargetClass$$EnhancerByCGLIB$$a0f953e6 targetclass$$enhancerbycglib$$a0f953e6 = (TargetClass$$EnhancerByCGLIB$$a0f953e6)obj;
if(targetclass$$enhancerbycglib$$a0f953e6.CGLIB$BOUND) goto _L2; else goto _L1
_L1:
Object obj1;
targetclass$$enhancerbycglib$$a0f953e6.CGLIB$BOUND = true;
obj1 = CGLIB$THREAD_CALLBACKS.get();
obj1;
if(obj1 != null) goto _L4; else goto _L3
_L3:
JVM INSTR pop ;
CGLIB$STATIC_CALLBACKS;
if(CGLIB$STATIC_CALLBACKS != null) goto _L4; else goto _L5
_L5:
JVM INSTR pop ;
goto _L2
_L4:
(Callback[]);
targetclass$$enhancerbycglib$$a0f953e6;
JVM INSTR swap ;
0;
JVM INSTR aaload ;
(MethodInterceptor);
CGLIB$CALLBACK_0;
_L2:
}
public Object newInstance(Callback acallback[])
{
CGLIB$SET_THREAD_CALLBACKS(acallback);
CGLIB$SET_THREAD_CALLBACKS(null);
return new TargetClass$$EnhancerByCGLIB$$a0f953e6();
}
public Object newInstance(Callback callback)
{
CGLIB$SET_THREAD_CALLBACKS(new Callback[] {
callback
});
CGLIB$SET_THREAD_CALLBACKS(null);
return new TargetClass$$EnhancerByCGLIB$$a0f953e6();
}
public Object newInstance(Class aclass[], Object aobj[], Callback acallback[])
{
CGLIB$SET_THREAD_CALLBACKS(acallback);
JVM INSTR new #2 ;
JVM INSTR dup ;
aclass;
aclass.length;
JVM INSTR tableswitch 0 0: default 35
// 0 28;
goto _L1 _L2
_L2:
JVM INSTR pop ;
TargetClass$$EnhancerByCGLIB$$a0f953e6();
goto _L3
_L1:
JVM INSTR pop ;
throw new IllegalArgumentException("Constructor not found");
_L3:
CGLIB$SET_THREAD_CALLBACKS(null);
return;
}
public Callback getCallback(int i)
{
CGLIB$BIND_CALLBACKS(this);
this;
i;
JVM INSTR tableswitch 0 0: default 30
// 0 24;
goto _L1 _L2
_L2:
CGLIB$CALLBACK_0;
goto _L3
_L1:
JVM INSTR pop ;
null;
_L3:
return;
}
public void setCallback(int i, Callback callback)
{
this;
callback;
i;
JVM INSTR tableswitch 0 0: default 29
// 0 20;
goto _L1 _L2
_L2:
(MethodInterceptor);
CGLIB$CALLBACK_0;
goto _L3
_L1:
JVM INSTR pop2 ;
_L3:
}
public Callback[] getCallbacks()
{
CGLIB$BIND_CALLBACKS(this);
this;
return (new Callback[] {
CGLIB$CALLBACK_0
});
}
public void setCallbacks(Callback acallback[])
{
this;
acallback;
JVM INSTR dup2 ;
0;
JVM INSTR aaload ;
(MethodInterceptor);
CGLIB$CALLBACK_0;
}
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$create$0$Method;
private static final MethodProxy CGLIB$create$0$Proxy;
private static final Object CGLIB$emptyArgs[];
private static final Method CGLIB$update$1$Method;
private static final MethodProxy CGLIB$update$1$Proxy;
private static final Method CGLIB$finalize$2$Method;
private static final MethodProxy CGLIB$finalize$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
private static final Method CGLIB$equals$5$Method;
private static final MethodProxy CGLIB$equals$5$Proxy;
private static final Method CGLIB$toString$6$Method;
private static final MethodProxy CGLIB$toString$6$Proxy;
static
{
CGLIB$STATICHOOK1();
}
public TargetClass$$EnhancerByCGLIB$$a0f953e6()
{
CGLIB$BIND_CALLBACKS(this);
}
}
看了这个反编译的代码不要凌乱啊
目前对cglib生成代理类研究不深,先在此记录如何使用cglib生成代理类;
cglib动态代理还有一个方面比jdk动态代理强大的地方就是:cglib允许为代理类的不同方法实现不同的代理
逻辑,实现代码如下:
public Object getProxyInstance(Class clazz) {
enhance.setSuperclass(clazz);
// enhance.setCallback(this);
enhance.setCallbackFilter(new MyCallbackFilter());//给代理类设置callBackFilter
enhance.setCallbacks(new Callback[]{new MyLazyLoader(), new MyFixedValue()});//设置对应的filter数组
return enhance.create();
}
class MyCallbackFilter implements CallbackFilter {
public int accept(Method method) {
if ("create".equals(method.getName())) {
return 0;//返回数字为代理类callBack数组的下标值,下标值对应的callBack就是代理类该方法使用的CallBack
} else if ("update".equals(method.getName())) {
return 1;
}
return 0;
}
public boolean equals(Object o) {
return false;
}
}
代理类可以设置一个CallBackFilter和一个CallBack数组,在CallBackFilter里定义每个方法使用CallBack数组里的CallBack,在对应的CallBack里定义方法的具体代理逻辑。
jdk的动态代理无法实现上述功能。