一、前言
Java中常见的代理有JDK代理和Cglib代理,下面讲下原理以及使用场景
二、JDK代理
2.1 试验测试
接口类:
public interface UserService { public abstract void add();
}
实现类:
public class UserServiceImpl implements UserService { @Override
public void add() { // TODO Auto-generated method stub
System.out.println("--------------------add----------------------");
}
}
InvocationHandler类
public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { super(); this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
PerformanceMonior.begin(target.getClass().getName()+"."+method.getName()); //System.out.println("-----------------begin "+method.getName()+"-----------------");
Object result = method.invoke(target, args); //System.out.println("-----------------end "+method.getName()+"-----------------");
PerformanceMonior.end(); return result;
} public Object getProxy(){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);
}
}
测试类
public static void main(String[] args) { //生成的代理类保存到磁盘
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
UserService service = new UserServiceImpl();
MyInvocationHandler handler = new MyInvocationHandler(service);
UserService proxy = (UserService) handler.getProxy();
proxy.add();
}
UserServiceImpl被JDK代理后的类,在项目的com.sun.proxy下面生成$Proxy0.class类
package com.sun.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;import proxy.JDK.UserService;public final class $Proxy0
extends Proxy
implements UserService{ private static Method m1; private static Method m3; private static Method m0; private static Method m2; public $Proxy0(InvocationHandler paramInvocationHandler)
{ super(paramInvocationHandler);
} public final void add()
{ try
{ //第一个参数是代理类本身,第二个是实现类的方法,第三个是参数
this.h.invoke(this, m3, null); return;
} catch (Error|RuntimeException localError)
{ throw localError;
} catch (Throwable localThrowable)
{ throw new UndeclaredThrowableException(localThrowable);
}
}
... static
{ try
{
m3 = Class.forName("proxy.JDK.UserService").getMethod("add", new Class[0]);
... return;
} catch (NoSuchMethodException localNoSuchMethodException)
{ throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
} catch (ClassNotFoundException localClassNotFoundException)
{ throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
也就是说main函数里面的proxy实际就是$Proxy0的一个实例对象。
2.2 源码分析
如时序图首先调用了newProxyInstance方法:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException{
... /*
* 查找或者生成代理类的大class类.
*/
Class<?> cl = getProxyClass0(loader, intfs); /*
*
使用代理类构造函数实例化一个对象
*/
try { final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { // create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return newInstance(cons, ih);
}
});
} else { return newInstance(cons, ih);
}
} catch (NoSuchMethodException e) { throw new InternalError(e.toString());
}
}
然后看下关键函数getProxyClass0
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded");
} // 使用缓存,如果缓存中存在由实现类加载器创建的代理类,则直接返回,否者使用ProxyClassFactory创建代理类的Class
return proxyClassCache.get(loader, interfaces);
}
在看下ProxyClassFactory的apply函数:
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
... /*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num; /*
* 根据接口类生成代理类.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces); try { return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
... throw new IllegalArgumentException(e.toString());
}
}
三、Cglib代理
3.1 试验测试
测试代码
public void testCglibProxy() {//生成代理类到本地
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/zhuizhumengxiang/Downloads");
UserServiceImpl service = new UserServiceImpl();
CglibProxy cp = new CglibProxy();
UserService proxy = (UserService) cp.getProxy(service.getClass());
proxy.add();
proxy.sub();
proxy.hello("zlx");
proxy.service("zlx");
proxy.toString();
}
MethodInterceptor类:
public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback( this); //enhancer.setCallbackType(clazz);;
return enhancer.create();
} @Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
PerformanceMonior.begin(obj.getClass().getName()+"."+method.getName());
Object result = proxy.invokeSuper(obj, args); // Object result = method.invoke(obj, args);
PerformanceMonior.end(); return result;
}
}
生成的代理类反编译后:
package proxy.JDK;import java.lang.reflect.Method;import org.springframework.cglib.proxy.Callback;import org.springframework.cglib.proxy.Factory;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;public class UserServiceImpl$$EnhancerByCGLIB$$a68ccf10
extends UserServiceImpl
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$add$0$Method; private static final MethodProxy CGLIB$add$0$Proxy; private static final Object[] CGLIB$emptyArgs; private static final Method CGLIB$service$1$Method; private static final MethodProxy CGLIB$service$1$Proxy; private static final Method CGLIB$testAnnotaion$2$Method; private static final MethodProxy CGLIB$testAnnotaion$2$Proxy; private static final Method CGLIB$testAnnotaion2$3$Method; private static final MethodProxy CGLIB$testAnnotaion2$3$Proxy; private static final Method CGLIB$hello$4$Method; private static final MethodProxy CGLIB$hello$4$Proxy; private static final Method CGLIB$sub$5$Method; private static final MethodProxy CGLIB$sub$5$Proxy; private static final Method CGLIB$finalize$6$Method; private static final MethodProxy CGLIB$finalize$6$Proxy; private static final Method CGLIB$equals$7$Method; private static final MethodProxy CGLIB$equals$7$Proxy; private static final Method CGLIB$toString$8$Method; private static final MethodProxy CGLIB$toString$8$Proxy; private static final Method CGLIB$hashCode$9$Method; private static final MethodProxy CGLIB$hashCode$9$Proxy; private static final Method CGLIB$clone$10$Method; private static final MethodProxy CGLIB$clone$10$Proxy;
... final void CGLIB$add$0()
{ super.add();
} public final void add()
{
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.add();
}
... public UserServiceImpl$$EnhancerByCGLIB$$a68ccf10()
{
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)
{
a68ccf10 locala68ccf10 = (a68ccf10)paramObject; if (!locala68ccf10.CGLIB$BOUND)
{
locala68ccf10.CGLIB$BOUND = true;
Object tmp23_20 = CGLIB$THREAD_CALLBACKS.get(); if (tmp23_20 == null)
{
tmp23_20;
CGLIB$STATIC_CALLBACKS;
}
locala68ccf10.CGLIB$CALLBACK_0 = (tmp31_28 == null ? tmp31_28 : (MethodInterceptor)((Callback[])tmp23_20)[0]);
}
} public Object newInstance(Callback[] paramArrayOfCallback)
{
CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
CGLIB$SET_THREAD_CALLBACKS(null); return new a68ccf10();
} public Object newInstance(Callback paramCallback)
{
CGLIB$SET_THREAD_CALLBACKS(new Callback[] { paramCallback });
CGLIB$SET_THREAD_CALLBACKS(null); return new a68ccf10();
} 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是通过直接继承被代理类,并委托为回调函数来做具体的事情:
从代理类里面可知道对于原来的add函数,代理类里面对应了两个函数分布是add 和CGLIB0CGLIB
0
3.2 源码分析
如图首先设置被代理类,然后设置自己写的方法拦截器,然后创建创建代理类的Class对象,并调用代理类的CGLIB$SET_THREAD_CALLBACKS方法设置回调。
四、比较
对应JDK动态代理机制是委托机制,具体说动态实现接口类,在动态生成的实现类里面委托为hanlder去调用原始实现类方法。$ProxyAoImpl
,那么$ProxyAoImpl
能赋值给Abo?能够赋值给AboImpl?
$ProxyAoImpl
是能够赋值给Abo的,因为前者间接实现了后者,但是$ProxyAoImpl
不能赋值给AboImpl因为他们没有继承或者实现关系。所以回顾下自己项目中Rpc里面autowired时候都是对bo类进行的,而不是对boimpl,并且我们的boimpl类一般都是配置了事务切面被代理过的。
对应Cglib则使用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。
另外JDK代理只能对接口进行代理,Cglib则是对实现类进行代理。