代理模式分为三种角色:
- 抽象主题类:通过接口或抽象类型声明真实主题和代理对象实现的业务方法。
- 真实主题类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
- 代理类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制和扩展真实主题的功能。
public interface ISubject {
void doSomeThings();
}
/**
* 真实对象
*/
class RealSubject implements ISubject{
@Override
public void doSomeThings() {
System.out.println("doSomeThings");
}
}
/**
* 代理对象
*/
class ProxySubject implements ISubject{
private RealSubject realSubject = new RealSubject();
@Override
public void doSomeThings() {
System.out.println("before do some things");
realSubject.doSomeThings();
System.out.println("after do some things");
}
public static void main(String[] args) {
//创建代理类对象
ProxySubject proxySubject = new ProxySubject();
proxySubject.doSomeThings();
}
}
public interface ISubject {
void doSomeThings();
}
/**
* 真实对象
*/
class RealSubject implements ISubject{
@Override
public void doSomeThings() {
System.out.println("doSomeThings");
}
}
/**
* 代理工厂
*/
class ProxyFactory {
private RealSubject realSubject = new RealSubject();
/**
* 获取代理对象
*/
public ISubject getProxySubject(){
/**
* ClassLoader loader:类加载器,用于加载代理类,可以通过目标对象获取类加载器
* Class<?>[] interfaces: 代理类实现的接口的字节码对象
* InvocationHandler h :代理对象的调用处理程序
*/
final Class<? extends RealSubject> subjectClass = realSubject.getClass();
ISubject proxySubject = (ISubject)Proxy.newProxyInstance(
subjectClass.getClassLoader(),
subjectClass.getInterfaces(),
new InvocationHandler() {
/**
* @param proxy 代理对象
* @param method 将接口中的方法封装成Method类型的对象
* @param args 接口方法的参数
* @return 接口方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before do some things");
Object obj = method.invoke(realSubject, args);
System.out.println("after do some things");
return obj;
}
});
return proxySubject;
}
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory();
ISubject proxySubject = factory.getProxySubject();
proxySubject.doSomeThings();
}
}
根据Arthas获得生成的代理类
package com.sun.proxy;
import com.example.ISubject;
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 ISubject {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler invocationHandler) {
super(invocationHandler);
}
public final boolean equals(Object object) {
try {
return (Boolean)this.h.invoke(this, m1, new Object[]{object});
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString() {
try {
return (String)this.h.invoke(this, m2, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void doSomeThings() {
try {
this.h.invoke(this, m3, null);
return;
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode() {
try {
return (Integer)this.h.invoke(this, m0, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("com.example.ISubject").getMethod("doSomeThings", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException noSuchMethodException) {
throw new NoSuchMethodError(noSuchMethodException.getMessage());
}
catch (ClassNotFoundException classNotFoundException) {
throw new NoClassDefFoundError(classNotFoundException.getMessage());
}
}
}
- 代理类($Proxy0)和真实对象实现类同样的接口
- 代理类将实现InvocationHandler的子类传递给父类Proxy
- 在代理类实现接口,在接口调用父类的invoke方法
Proxy.newProxyInstance解读
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,
InvocationHandler h)
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
//java的安全管理器,可参考文章https://www.cnblogs.com/yiwangzhibujian/p/6207212.html
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
// 获取(缓存中如果有)或者生成目标代理类
Class<?> cl = getProxyClass0(loader, intfs);
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// 通过构造函数去生成一个目标代理类的实例。
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 如果构造函数并不是public修饰的,那么设置代理类可以通过反射来访问
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
}
以上代码和实际的源码有所不同,精简了一下,方便阅读。上面函数主要完成两件事:生成代理类的字节码对象和通过代理类的字节码对象创建实例。另外需要关注一下@CallerSensitive,该注解标注 jdk内有些方法,jvm的开发者认为这些方法危险,不希望开发者调用,就把这种危险的方法用 @CallerSensitive修饰,并在“jvm”级别检查,并且@CallerSensitive 有个特殊之处,必须由 启动类classloader加载(如rt.jar ),才可以被识别。
获得代理类的字节码对象,会根据反射调用代理类有参构造器,参数类型是InvocationHandler,其实在代理类中的构造器会调用其父类Proxy,来初始化Proxy类的成员变量protected InvocationHandler h; 之后代理类实现接口的方法里,其实是调用父类Proxy中InvocationHandler类型的变量的invoke方法。
接下来会先从缓存里获取目标代理类,如果缓存没有才创建代理类,在Proxy类定义一个成员变量
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
构造WeakCache对象需要传入两个类型分别是KeyFactory和ProxyClassFactory的参数,这两个类都是Proxy的静态内部类。
KeyFactory源码如下
private static final class KeyFactory
implements BiFunction<ClassLoader, Class<?>[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
switch (interfaces.length) {
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}
KeyFactory实现函数式接口BiFunction,重写apply方法,该方法主要根据目标类继承接口的个数不同,生成相应接口的虚引用,这些Key*类都继承WeakReference。
ProxyClassFactory源码如下
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// 代理类名前缀
private static final String proxyClassNamePrefix = "$Proxy";
// 代理类名后缀
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
// 判断相同名字的接口是否是同一个Class对象
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
// 验证是否是接口类型
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
// 验证是否有重复的实现
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
//如果目标类实现的接口,有不是public修饰的。那么目标代理类生成的路径会在该接口所在目录下
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// 如果目标类所实现的接口都是被public修饰的,那么会动态生成在com.sun.proxy下,而且被public final修饰
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
.....
}
}
}
ProxyClassFactory就是生成代理类的工厂,需要注意的时,设置代理类所在的包路径。判断依据:
- 如果存在非public的接口并且不在同一个包内,那么抛出异常。
- 如果存在非public的接口,但是在同一个包内,那么在该接口所在的路径就是目标类的生成路径。
- 如果所有接口都是public类型的,那么目标类的路径设置为com.sum.proxy.
前面讲到代理会先从缓存里获取,那我们看看这个缓存的构造吧
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
= new ConcurrentHashMap<>();
从WeaCache这个缓存数据结构里,可以看出一二级key整合起来对应一个value的组合,即(key,sub-key)-> (value),其中key是指代理的classLoader,sub-key指目标函数的interfaces,value指$Proxy.class
接下来看WeaChe核心实现get源码
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
//对已经被gc的实例从缓存中移除
expungeStaleEntries();
/**
* 根据传入的key(classloader)和引用队列包装成一个CacheKey类型的key
* 如果key为null,则返回一个Object类型的对象,否则返回一个CacheKey类型的对象
* CacheKey继承WeakReference,是一个弱引用类型的
*/
Object cacheKey = CacheKey.valueOf(key, refQueue);
//通过CacheKey获取到二级缓存实例
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
//如果不存在该一级缓存,则对该一级缓存进行初始化
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
/**
* 通过sub-key函数将key/parameter计算出sub-key,并且这里计算的结果不允许为空
* key是classloader,parameter是interfaces
* 计算方式已经在前面KeyFactory源码讲过了
*/
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
//从二级缓存中获取结果获取器
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
//这里进入死循环,直到获取到结果为止
while (true) {
if (supplier != null) {
/**
*这里获取到值可能是一个工厂或者一个缓存实例
*如果返回一个Factory类型的工厂,Factory实现了Supplier接口,在apply方法就会生成代理类
*而在apply方法又调用ProxyClassFactory的方法来真正生成代理类
*/
V value = supplier.get();
if (value != null) {
return value;
}
}
//这里懒加载工厂,实例化一个内置Factory,该Factory实现了Supplier
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
//这里如果supplier为空,则直接将factory放入二级缓存
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
supplier = factory;
}
// else retry with winning supplier
} else {
//如果supplier非空,但是获取值为空则进行替换二级缓存中factory(或者supplier)
if (valuesMap.replace(subKey, supplier, factory)) {
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
- 根据一级键(根据类加载器classLoader)、二级键(根据接口interfaces)从缓存中来获取目标代理类对象supplier 。
- supplier可能是一个创建成功的动态代理对象。也可能是一个创建代理对象的工厂Factory(第一次的话就是他)。
- 因为第一次动态代理的时候,缓存肯定是null。因此实际上就会做一些初始化操作。
- 就是创建一个Factory工厂,通过工厂来创建一个动态代理对象(最终的对象),这里实际调用ProxyClassFactory的方法来生成的。
/**
* 真实对象
*/
class RealSubject {
public void doSomeThings() {
System.out.println("doSomeThings");
}
}
/**
* 代理工厂
*/
class ProxyFactory{
/**
* 获取代理对象
*/
public RealSubject getProxySubject(){
//创建Enhancer对象,类似于JDK代理中的Proxy类
Enhancer enhancer = new Enhancer();
//设置父类的字节码对象
enhancer.setSuperclass(RealSubject.class);
//设置回调函数,这里参数是MethodInterceptor的子类
enhancer.setCallback(new MethodInterceptor() {
/**
* @param o 代理对象(增强的对象)
* @param method 被拦截的方法(需要增强的方法)
* @param objects 方法入参
* @param methodProxy 用于调用原始方法 保存方法的一些信息
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before do some things");
Object returnValue = methodProxy.invokeSuper(o, objects);
System.out.println("after do some things");
return returnValue;
}
});
//创建代理对象
RealSubject proxyObject = (RealSubject) enhancer.create();
return proxyObject;
}
public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory();
final RealSubject proxySubject = proxyFactory.getProxySubject();
proxySubject.doSomeThings();
}
}
通过以下代码:System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:\\项目\\demo\\proxy");
可以输出代理类字节码文件
这三个文件有什么作用呢,且听我细细道来哈。
1)代理类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.example;
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$$2244f8c3 extends RealSubject 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$doSomeThings$0$Method;
private static final MethodProxy CGLIB$doSomeThings$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$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;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.example.RealSubject$$EnhancerByCGLIB$$2244f8c3");
Class var1;
CGLIB$doSomeThings$0$Method = ReflectUtils.findMethods(new String[]{"doSomeThings", "()V"}, (var1 = Class.forName("com.example.RealSubject")).getDeclaredMethods())[0];
CGLIB$doSomeThings$0$Proxy = MethodProxy.create(var1, var0, "()V", "doSomeThings", "CGLIB$doSomeThings$0");
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
}
final void CGLIB$doSomeThings$0() {
super.doSomeThings();
}
public final void doSomeThings() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$doSomeThings$0$Method, CGLIB$emptyArgs, CGLIB$doSomeThings$0$Proxy);
} else {
super.doSomeThings();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$2() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -944907599:
if (var10000.equals("doSomeThings()V")) {
return CGLIB$doSomeThings$0$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
public RealSubject$$EnhancerByCGLIB$$2244f8c3() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
RealSubject$$EnhancerByCGLIB$$2244f8c3 var1 = (RealSubject$$EnhancerByCGLIB$$2244f8c3)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
RealSubject$$EnhancerByCGLIB$$2244f8c3 var10000 = new RealSubject$$EnhancerByCGLIB$$2244f8c3();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
RealSubject$$EnhancerByCGLIB$$2244f8c3 var10000 = new RealSubject$$EnhancerByCGLIB$$2244f8c3();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
RealSubject$$EnhancerByCGLIB$$2244f8c3 var10000 = new RealSubject$$EnhancerByCGLIB$$2244f8c3;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
从反编译的代理类字节码文件可以得出以下结论:
(1)代理通过继承目标类,并重写目标类方法实现代理的。
(2)对于父类的每个方法,代理里都生成两个方法,分别是:一个是重写父类的方法,一个是CGLIB$xxxx$x方法,前者是实现目标方法的增强的。接下来我重点分析代理类的doSomeThings方法。
public final void doSomeThings() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$doSomeThings$0$Method, CGLIB$emptyArgs, CGLIB$doSomeThings$0$Proxy);
} else {
super.doSomeThings();
}
}
先判断MethodInterceptor是否为null,也就是判断是否实现了该接口,如果没有,调用CGLIB$BIND_CALLBACKS方法来获取拦截对象,CGLIB$BIND_CALLBACKS代码如下
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
RealSubject$$EnhancerByCGLIB$$2244f8c3 var1 = (RealSubject$$EnhancerByCGLIB$$2244f8c3)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
(1)该方法会先从CGLIB$THREAD_CALLBACKS中get拦截对象,如果获取不到的话,再从CGLIB$STATIC_CALLBACKS来获取
(2)如果获取到则走代理,否则认为该方法不需要代理
(3)然后调用MethodInterceptor的intercept方法
var10000.intercept(this, CGLIB$doSomeThings$0$Method, CGLIB$emptyArgs, CGLIB$doSomeThings$0$Proxy);
参数分别是代理类对象本身,本拦截的方法对象,方法入参和用于调用被拦截方法的方法代理对象,那第四个参数有什么作用呢?其实第四个参数决定了cglib代理高效的原因。cglib没有通过反射调用目标类方法,而是为每个方法分配索引,通过索引查找具体方法,类似于直接调用。
前面生成的三个文件,除了代理类,剩下的是索引文件,接下来看一下MethodInterceptor的intercept方法
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before do some things");
Object returnValue = methodProxy.invokeSuper(o, objects);
System.out.println("after do some things");
return returnValue;
}
继续看MethodProxy的invokeSuper方法
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
init()方法主要完成对MethodProxy类成员变量fastClassInfo初始化,初始化完成后可知fci中对应的两个成员变量分别对应上面生成的两个索引文件,对于
fci.f2.invoke(fci.i2, obj, args);
fci
为封装了两个FastClass
的静态类FastClassInfo
f2
为代理类的文件索引类i2
为具体方法索引
FastClassInfo类结构如下
private static class FastClassInfo
{
FastClass f1;
FastClass f2;
int i1;
int i2;
}
FasfClassInfo包含两个FastClass类型的成员变量,其中FastClass有两个重要方法
getIndex用来生成对应方法的索引的,生成规则主要根据方法名+方法的描述符实现的,
invoke根据索引调用相应的方法
abstract public Object invoke(int index, Object obj, Object[] args) throws InvocationTargetException;
abstract public int getIndex(Signature sig);
索引字节码文件代码如下
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -944907599:
if (var10000.equals("doSomeThings()V")) {
return 0;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 1;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 2;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 3;
}
}
return -1;
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
RealSubject var10000 = (RealSubject)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.doSomeThings();
return null;
case 1:
return new Boolean(var10000.equals(var3[0]));
case 2:
return var10000.toString();
case 3:
return new Integer(var10000.hashCode());
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
/**
* 代理工厂
*/
class MyProxyFactory {
/**
* 获取代理对象
*/
public Object getProxy(Class<?> clazz) throws Exception {
// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
// 设置需要创建子类的父类
proxyFactory.setSuperclass(clazz);
Object proxy = proxyFactory.createClass().newInstance();
((ProxyObject) proxy).setHandler(new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] objects) throws Throwable {
System.out.println("before do some things");
Object returnValue = proceed.invoke(self, objects);
System.out.println("after do some things");
return returnValue;
}
});
return proxy;
}
public static void main(String[] args) throws Exception {
MyProxyFactory factory = new MyProxyFactory();
RealSubject proxy = (RealSubject) factory.getProxy(RealSubject.class);
proxy.doSomeThings();
}
}
在生成代理类之前,通过给ProxyFactory类的成员变量writeDirectory赋值,会得到生成的代理类文件。
public class RealSubject_$$_jvst886_0 extends RealSubject implements ProxyObject {
private MethodHandler handler;
public static byte[] _filter_signature;
public static final long serialVersionUID;
private static Method[] _methods_;
public RealSubject_$$_jvst886_0() {
this.handler = RuntimeSupport.default_interceptor;
super();
}
public final Object _d0clone() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
Method[] var1 = _methods_;
return (Object)this.handler.invoke(this, var1[0], var1[1], new Object[0]);
}
public final void _d1doSomeThings() {
super.doSomeThings();
}
public final void doSomeThings() {
Method[] var1 = _methods_;
this.handler.invoke(this, var1[2], var1[3], new Object[0]);
}
public final boolean _d2equals(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
Method[] var2 = _methods_;
return (Boolean)this.handler.invoke(this, var2[4], var2[5], new Object[]{var1});
}
public final void _d3finalize() throws Throwable {
super.finalize();
}
protected final void finalize() throws Throwable {
Method[] var1 = _methods_;
this.handler.invoke(this, var1[6], var1[7], new Object[0]);
}
public final int _d5hashCode() {
return super.hashCode();
}
public final int hashCode() {
Method[] var1 = _methods_;
return (Integer)this.handler.invoke(this, var1[10], var1[11], new Object[0]);
}
public final String _d8toString() {
return super.toString();
}
public final String toString() {
Method[] var1 = _methods_;
return (String)this.handler.invoke(this, var1[16], var1[17], new Object[0]);
}
static {
Method[] var0 = new Method[24];
Class var1 = Class.forName("com.example.RealSubject_$$_jvst886_0");
RuntimeSupport.find2Methods(var1, "clone", "_d0clone", 0, "()Ljava/lang/Object;", var0);
RuntimeSupport.find2Methods(var1, "doSomeThings", "_d1doSomeThings", 2, "()V", var0);
RuntimeSupport.find2Methods(var1, "equals", "_d2equals", 4, "(Ljava/lang/Object;)Z", var0);
RuntimeSupport.find2Methods(var1, "finalize", "_d3finalize", 6, "()V", var0);
RuntimeSupport.find2Methods(var1, "hashCode", "_d5hashCode", 10, "()I", var0);
RuntimeSupport.find2Methods(var1, "toString", "_d8toString", 16, "()Ljava/lang/String;", var0);
_methods_ = var0;
serialVersionUID = -1L;
}
public void setHandler(MethodHandler var1) {
this.handler = var1;
}
public MethodHandler getHandler() {
return this.handler;
}
Object writeReplace() throws ObjectStreamException {
return RuntimeSupport.makeSerializedProxy(this);
}
}
这篇文章写了大约有半个月吧,每次都是下班回家看看,研究一下,当然,还有很多不足吧,鉴于个人水平有限,只能尽力而为,欢迎读者指正,共同进步,谢谢。
因篇幅问题不能全部显示,请点此查看更多更全内容