1.说明
代理模式的解释:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。
2.类型:
CGLib动态代理和JDK动态代理
3.使用介绍
(1)CGLib动态代理的使用
使用示例:
1、针对代理类的示例
代码语言:javascript复制//构建代理对象
public class TestObject {
public void test(){
System.out.println("test");
}
public void test1(){
System.out.println("test1");
}
}
//构建方法拦截器
public class MyMethodInterceptor implements MethodInterceptor {
//Object为由CGLib生成的代理类实例;Method为上文中实体类所调用的被代理的方法引用;Object[]为参数值列表;MethodProxy 为生成的代理类对方法的代理引用
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before..");
Object result = methodProxy.invokeSuper(o,objects);
System.out.println("after..");
return result;
}
}
//生成代理步骤
public static void main(String[] args) {
Enhancer enhancer = new Enhancer(); //构造出加强器对象
enhancer.setSuperclass(TestObject.class); //将代理类设置进去
enhancer.setCallback(new MyMethodInterceptor());
TestObject testObject= (TestObject)enhancer.create();
testObject.test();
}
2、针对代理接口的示例
代码语言:javascript复制public interface UserInterface {
public void test();
public void test1();
}
public class User implements UserInterface {
@Override
public void test() {
System.out.println("test");
}
@Override
public void test1() {
System.out.println("test1");
}
}
public class MyInterfaceMyMethodInterceptor implements MethodInterceptor {
Object object;
public MyInterfaceMyMethodInterceptor(Object object) {
this.object = object;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before..");
Object result = methodProxy.invoke(object,objects);
System.out.println("after..");
return result;
}
}
public static void main(final String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserInterface.class);
enhancer.setCallback(new MyInterfaceMyMethodInterceptor(new User()));
UserInterface userInterface = (UserInterface) enhancer.create();
userInterface.test();
}
(2)JDK动态代理的使用
代码语言:javascript复制public interface UserInterface {
public void test();
public void test1();
}
public class User implements UserInterface {
@Override
public void test() {
System.out.println("test");
}
@Override
public void test1() {
System.out.println("test1");
}
}
public class MyInvocationHandler implements InvocationHandler {
Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before..");
Object result = method.invoke(target,args);
System.out.println("after..");
return result;
}
}
public static void main(String[] args) {
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new User());
UserInterface userInterface = (UserInterface) Proxy.newProxyInstance(JDKDemo.class.getClassLoader(), new Class[]{UserInterface.class}, myInvocationHandler);
userInterface.test();
}
4.底层分析(通过JVM添加参数 -Dcglib.debugLocation=D:IdeaProjectscglibcglibtargetclasses【这个便是代理对象的存储路径】)
代理类的class类(依据文件TestObject
783a36a0.class)
(1)代码展示
代码语言:javascript复制//继承了代理类
public class TestObject$$EnhancerByCGLIB$$783a36a0 extends TestObject 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$test$0$Method;
private static final MethodProxy CGLIB$test$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$test1$1$Method;
private static final MethodProxy CGLIB$test1$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 var0 = Class.forName("com.xiangxue.jack.aop.daili.TestObject$$EnhancerByCGLIB$$783a36a0");
Class var1;
//从目标类中拿出对应的方法构建成方法对象
Method[] var10000 = ReflectUtils.findMethods(new String[]{"test", "()V", "test1", "()V"}, (var1 = Class.forName("com.xiangxue.jack.aop.daili.TestObject")).getDeclaredMethods());
CGLIB$test$0$Method = var10000[0];
//针对方法对象构建出代理对象
CGLIB$test$0$Proxy = MethodProxy.create(var1, var0, "()V", "test", "CGLIB$test$0");
CGLIB$test1$1$Method = var10000[1];
CGLIB$test1$1$Proxy = MethodProxy.create(var1, var0, "()V", "test1", "CGLIB$test1$1");
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$2$Method = var10000[0];
CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
CGLIB$toString$3$Method = var10000[1];
CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
CGLIB$hashCode$4$Method = var10000[2];
CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
CGLIB$clone$5$Method = var10000[3];
CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
}
//去执行父类的test()方法
final void CGLIB$test$0() {
super.test();
}
//重写了父类的test()方法
public final void test() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this); //给 CGLIB$CALLBACK_0 属性赋值
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
//四个参数分别为(当前的代理对象,方法,参数,未知)
var10000.intercept(this, CGLIB$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy);
} else {
super.test();
}
}
final void CGLIB$test1$1() {
super.test1();
}
public final void test1() {
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$test1$1$Method, CGLIB$emptyArgs, CGLIB$test1$1$Proxy);
} else {
super.test1();
}
}
final boolean CGLIB$equals$2(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$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$3() {
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$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
}
final int CGLIB$hashCode$4() {
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$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$5() 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$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -1422510685:
if (var10000.equals("test()V")) {
return CGLIB$test$0$Proxy;
}
break;
case -1147892426:
if (var10000.equals("test1()V")) {
return CGLIB$test1$1$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$5$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$2$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$3$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$4$Proxy;
}
}
return null;
}
public TestObject$$EnhancerByCGLIB$$783a36a0() {
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) {
TestObject$$EnhancerByCGLIB$$783a36a0 var1 = (TestObject$$EnhancerByCGLIB$$783a36a0)var0;
if (!var1.CGLIB$BOUND) { //一开始为false,布尔值的默认值
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get(); //从当前线程的ThreadLocal中获取
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);
TestObject$$EnhancerByCGLIB$$783a36a0 var10000 = new TestObject$$EnhancerByCGLIB$$783a36a0();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
TestObject$$EnhancerByCGLIB$$783a36a0 var10000 = new TestObject$$EnhancerByCGLIB$$783a36a0();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
TestObject$$EnhancerByCGLIB$$783a36a0 var10000 = new TestObject$$EnhancerByCGLIB$$783a36a0;
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();
}
}
(2)调用流程说明
当代理对象被调用的时候【假设为test()方法】
代码语言:javascript复制public final void test() {
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$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy);
} else {
super.test();
}
}
CGLIBCALLBACK_0该属性一开始是没有值的(因为初始化过程没有赋值的步骤),而获取值得步骤在于 CGLIBBIND_CALLBACKS(this);这一步。
代码语言:javascript复制private static final void CGLIB$BIND_CALLBACKS(Object var0) {
TestObject$$EnhancerByCGLIB$$783a36a0 var1 = (TestObject$$EnhancerByCGLIB$$783a36a0)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];
}
}
这里面var1明显是指类本身,故CGLIBBOUND会发现是布尔值类型,默认是false。而CGLIBTHREAD_CALLBACKS在静态代码块中被赋予了ThreadLocal,所以是打算从当前线程的ThreadLocal中获取。而CGLIB
(3)问题汇总
1.这里有个问题ThreadLocal是什么时候被赋值的?
是在 CGLIBSET_THREAD_CALLBACKS 这个方法中被赋值的,CGLIBSET_THREAD_CALLBACKS这个方法又是在newInstance方法【生成代理对象的方法】中被执行。
2.test()⽅法内会去调⽤所设置的Callbacks中的intercept(),相当于执⾏增强逻辑,如果没有Callbacks,则会执⾏super.test(),那么我们⾃然能想到,如果不设置Callbacks,那是不是就能正常执⾏呢?(是不能正常执行的)
- 情况1,enhancer.setCallback(null);
异常出现在:createHelper()方法#preValidate()#CallbackInfo.determineTypes(callbacks, false);
会报java.lang.IllegalStateException: Callback is null
- 情况2,不设置enhancer.setCallback
createHelper()方法#preValidate()#CallbackInfo.determineTypes(callbacks, false);
会报java.lang.NullPointerException
(4)分析说明
- 明显会继承代理类,还会实现Factory接口。 动态代理类持有 MethodInterceptor 动态代理类会重写父类的非 final、private 方法【 如test() 】,也会构建自己的方法(cglib 方法),构建方式:CGLIB” “父类方法名【 如CGLIBtest0 】。 cglib 方法的方法体:super.方法名,直接调用父类;重写方法:它会调用拦截器中的 intercept() 方法。 methodProxy.invokeSuper() 方法会调用动态代理类中的 cglib 方法;methodProxy.invoke() 方法会调用动态代理类中的重写方法
5.JDK动态代理源码分析(还未写全,待续)
(1)Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
代码语言:javascript复制@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//去拿到代理类
Class<?> cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//拿到代理类的构造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
//拿到拦截器对象
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//然后把拦截器传给构造方法
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {..} catch (InvocationTargetException e) {...} catch (NoSuchMethodException e) {... }
}
6.CGLib源码分析
(1)Enhancer.create()
代码语言:javascript复制public Object create() {
classOnly = false;
argumentTypes = null;
//执行创建
return createHelper();
}
(2)Enhancer.createHelper()
代码语言:javascript复制private Object createHelper() {
//校验callbackTypes,filter是否为空,已经为空的处理
preValidate();
// 通过newInstance方法生成了一个EnhancerKey代理对象,该代理对象里面保存了用户所设置的代理信息
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
//设置当前Enhancer的代理类的key标识
this.currentKey = key;
// 调用父类AbstractClassGenerator的方法去创建代理对象
Object result = super.create(key);
return result;
}
(3)AbstractClassGenerator.create(Object key)
代码语言:javascript复制protected Object create(Object key) {
try {
ClassLoader loader = getClassLoader();
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
// 构造方法中会生成一个生成代理类的lambda表达式
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
// 利用ClassLoaderData拿到代理类,ClassLoaderData中有一个generatedClasses用来缓存生成好的代理类
// this就是Enhancer
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
// 调用代理类的构造方法生成一个代理对象
return firstInstance((Class) obj);
}
return nextInstance(obj);
} catch (RuntimeException e) {...} catch (Error e) {...} catch (Exception e) {...}
}
(4)Enhancer.firstInstance((Class) obj) 与 Enhancer.createUsingReflection(type)
代码语言:javascript复制protected Object firstInstance(Class type) throws Exception {
if (classOnly) {
return type;
} else {
return createUsingReflection(type);
}
}
private Object createUsingReflection(Class type) {
// 设置callbacks到代理类中
setThreadCallbacks(type, callbacks);
try{
if (argumentTypes != null) {
//根据代理类创建代理对象
return ReflectUtils.newInstance(type, argumentTypes, arguments);
} else {
return ReflectUtils.newInstance(type);
}
}finally{
setThreadCallbacks(type, null);
}
}
private static void setThreadCallbacks(Class type, Callback[] callbacks) {
//private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS";
//这里便是调用将callbacks设置进入ThreadLocal里面
//也就是利用反射区执行
setCallbacksHelper(type, callbacks, SET_THREAD_CALLBACKS_NAME);
}
(5)ClassLoaderData.get(this, getUseCache())
代码语言:javascript复制public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {//也就是enhancer.setUseCache(false);会起到作用的地方,
// gen是Enhancer, ClassLoaderData.this中存储了EnhancerKey代理对象
return gen.generate(ClassLoaderData.this);
} else {//这里使用到缓存useCache=true
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
//Enhancer.generate
protected Class generate(ClassLoaderData data) {
validate();
//类的名字(可参考文件的名字)
if (superclass != null) {
setNamePrefix(superclass.getName());
} else if (interfaces != null) {
setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
}
//AbstractClassGenerator.generate
return super.generate(data);
}
//AbstractClassGenerator.generate
protected Class generate(ClassLoaderData data) {
Class gen;
Object save = CURRENT.get();
CURRENT.set(this);
try {
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) { throw ex..;}
synchronized (classLoader) {
String name = generateClassName(data.getUniqueNamePredicate());
data.reserveName(name);
this.setClassName(name);
}
if (attemptLoad) {
try {
gen = classLoader.loadClass(getClassName());
return gen;
} catch (ClassNotFoundException e) {..}
}
// this就是Enhancer,主要是在这个方法里面利用ASM技术,生成代理类里面的东西
byte[] b = strategy.generate(this);
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
if (protectionDomain == null) {
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
return gen;
} catch (RuntimeException e) {..} catch (Error e) {..} catch (Exception e) {..} finally {
CURRENT.set(save);
}
}
//代码generatedClasses.get(gen)进入
public V get(K key) {
// 这里得到就是EnhancerKey的代理对象
final KK cacheKey = keyMapper.apply(key);
Object v = map.get(cacheKey);
if (v != null && !(v instanceof FutureTask)) {
return (V) v;
}
// 传进去的key为Enhancer对象,cacheKey为EnhancerKey的代理对象,表示所设置的代理信息
return createEntry(key, cacheKey, v);
}
protected V createEntry(final K key, KK cacheKey, Object v) {
FutureTask<V> task;
boolean creator = false;
if (v != null) {
// Another thread is already loading an instance
task = (FutureTask<V>) v;
} else {
// loader.apply(key)就会去创建代理对象
task = new FutureTask<V>(new Callable<V>() {
public V call() throws Exception {
// 这里就会去创建代理类了,实际上也是调用gen.generate(ClassLoaderData.this);
return loader.apply(key);
}
});
Object prevTask = map.putIfAbsent(cacheKey, task);
if (prevTask == null) {
// creator does the load
creator = true;
task.run();
} else if (prevTask instanceof FutureTask) {
task = (FutureTask<V>) prevTask;
} else {
return (V) prevTask;
}
}
V result;
try {
result = task.get();
} catch (InterruptedException e) {...} catch (ExecutionException e) {...}
if (creator) {
// 代理类创建完之后会进行缓存
map.put(cacheKey, result);
}
return result;
}
7.MethodProxy源码分析
代码展示
代码语言:javascript复制public class UserService {
public void test(){
System.out.println("test");
}
}
public static void main(String[] args) {
final UserService target = new UserService();
Enhancer enhancer = new Enhancer();
enhancer.setUseCache(false);
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//为什么会存在有些报错有些不报错的问题?
if (method.getName().equals("test")) {
System.out.println("before...");
methodProxy.invoke(o, objects); //报栈溢出错误
methodProxy.invoke(target, objects);
methodProxy.invokeSuper(o, objects);
methodProxy.invokeSuper(target, objects); //报调⽤invokerSuper只能传⼊代理对象的错误
System.out.println("after...");
return null;
}
return method.invoke(target, objects);
}
});
UserService userService = (UserService) enhancer.create();
userService.test();
}
代码说明
在使用过程,我们常常遇到methodProxy上的方法使用问题,然而根本不知道为什么会这样。(虽然也不怎么会这样用)
进行分析
(1)MethodProxy是什么时候创建出来的?
从上面的字节码文件可以看到是在静态方法CGLIB$STATICHOOK1()中生成的。
源代码为(MethodProxy类#create方法)
代码语言:javascript复制create(Class c1, Class c2, String desc, String name1, String name2) {
// c1是TestObject
// c2是TestObject代理类[TestObject$$EnhancerByCGLIB$$783a36a0]
// desc被代理方法的返回值类型
// name1是被代理方法名比如test
// name2是代理类中的CGLIB$test$0方法,会调用super.test()
MethodProxy proxy = new MethodProxy();
proxy.sig1 = new Signature(name1, desc); // 被代理方法签名,也就是代表void test()
proxy.sig2 = new Signature(name2, desc); // 代理方法签名,也就是void CGLIB$test$0()
proxy.createInfo = new CreateInfo(c1, c2); // CreateInfo中表示的就是被代理类和代理类的信息
return proxy;
}
(2)MethodProxy的invoke方法与invokeSuper方法的区别?
先上代码:
代码语言:javascript复制public Object invoke(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
// f1表示被代理类的FastClass代理类,i1表示被代理方法的下标,这里就是去执行test()方法,具体执行的是哪个对象就看obj
return fci.f1.invoke(fci.i1, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (IllegalArgumentException e) {
if (fastClassInfo.i1 < 0)
throw new IllegalArgumentException("Protected method: " sig1);
throw e;
}
}
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
// f2表示UserService代理类的FastClass代理类,i2表示代理方法的下标,这里就是去执行CGLIB$test$0方法,具体执行的是哪个对象就看obj
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
说明
1.说白了,这个两个方法本身是根据不同的索引文件去找对应的方法,然后用传入对象,调用返回的方法。
2.这里面涉及了另外的两个字节码文件(便是上面存储路径下的):
TestObject
783a36a0
626f6578.class(这里面是代理类的方法索引)
TestObject
a3bbba2f.class(这里面是目标类的方法索引)
(3)FastClassInfo的生成过程
代码语言:javascript复制private void init(){
if (fastClassInfo == null) {
//采用双重判断 加锁达到只生成一次
synchronized (initLock) {
if (fastClassInfo == null) {
// CreateInfo中存储了代理类和被代理类
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
fci.f1 = helper(ci, ci.c1); // 被代理类的FastClass代理类,也就是TestObject$$FastClassByCGLIB$$a3bbba2f.class
fci.f2 = helper(ci, ci.c2); // 代理类的FastClass代理类,也就是TestObject$$EnhancerByCGLIB$$783a36a0$$FastClassByCGLIB$$626f6578.class
//被代理方法签名,也就是代表void test()
//代理方法签名,也就是void CGLIB$test$0()
// 预先生成每个方法所对应的下标,调用时就可以直接利用下标找到方法了,性能高
fci.i1 = fci.f1.getIndex(sig1); // 获取方法签名sig1在被代理类的FastClass代理类中的下标,后续根据下标找到对应的方法,sig1表示被代理方法test()
fci.i2 = fci.f2.getIndex(sig2); // 获取方法签名sigsig2在代理类的FastClass代理类中的下标,后续根据下标找到对应的方法,sig2表示代理方法CGLIB$test$0()
fastClassInfo = fci;
createInfo = null;
}
}
}
}
TestObject
783a36a0
626f6578.class代码展示(已经进行了部分删减,可以尝试自己去调试生产厂)
代码语言:javascript复制public class TestObject$$EnhancerByCGLIB$$783a36a0$$FastClassByCGLIB$$626f6578 extends FastClass {
public TestObject$$EnhancerByCGLIB$$783a36a0$$FastClassByCGLIB$$626f6578(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -1870561232:
if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {
return 16;
}
break;
...
case -1422510685:
if (var10000.equals("test()V")) {
return 7;
}
break;
case -1411812934:
if (var10000.equals("CGLIB$hashCode$4()I")) {
return 18;
}
break;
case -1147892426:
if (var10000.equals("test1()V")) {
return 9;
}
break;
...
case 446872140:
if (var10000.equals("CGLIB$test1$1()V")) {
return 21;
}
break;
...
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 1;
}
}
break;
...
case -336910199:
if (var1.equals("CGLIB$test1$1")) {
switch(var2.length) {
case 0:
return 21;
}
}
break;
..
case 3556498:
if (var1.equals("test")) {
switch(var2.length) {
case 0:
return 7;
}
}
break;
....
case 1951977611:
if (var1.equals("CGLIB$clone$5")) {
switch(var2.length) {
case 0:
return 19;
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
783a36a0 var10000 = (783a36a0)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return new Boolean(var10000.equals(var3[0]));
case 1:
return var10000.toString();
...
case 20:
return var10000.CGLIB$toString$3();
case 21:
var10000.CGLIB$test1$1();
return null;
case 22:
var10000.CGLIB$test$0();
return null;
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
783a36a0 var10000 = new 783a36a0;
783a36a0 var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.<init>();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 22;
}
}
8.拓展内容
ASM技术
引入包类
代码语言:javascript复制<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>7.1</version>
</dependency>
代码示例
代码语言:javascript复制public static void main(String[] args) throws IOException {
ClassWriter classWriter = new ClassWriter(0);
// 通过visit方法确定类的头部信息
classWriter.visit(Opcodes.V1_8,// java版本
Opcodes.ACC_PUBLIC,// 类修饰符
"Person", // 类的全限定名
null, "java/lang/Object", null);
//创建构造函数
MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>","()V");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
// 定义test方法
MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "test", "()V",
null, null);
methodVisitor.visitCode();
methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream;");
methodVisitor.visitLdcInsn("hello zyu");
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
"(Ljava/lang/String;)V");
methodVisitor.visitInsn(Opcodes.RETURN);
methodVisitor.visitMaxs(2, 2);
methodVisitor.visitEnd();
classWriter.visitEnd();
// 使classWriter类已经完成
// 将classWriter转换成字节数组写到文件里面去
byte[] data = classWriter.toByteArray();
//注:在Windows操作系统下必须保证文件夹要存在。
File file = new File("D:\IdeaProjects\AsmDemo\src\main\java\Person.class");
FileOutputStream fout = new FileOutputStream(file);
fout.write(data);
fout.close();
}
说明
- 运行完后会生成一个Person.class的字节码文件。
- 本质上有点类似于生成TXT文件的感觉,但是需要熟悉字节码指令等(其实本质上作为开发用到的不多,了解一下,知道个大概,以后用到在慢慢翻吧)
Javassist技术
引入包类
代码语言:javascript复制<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.25.0-GA</version>
</dependency>
代码示例
代码语言:javascript复制public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
ClassPool pool = ClassPool.getDefault();
// 1. 创建一个空类
CtClass cc = pool.makeClass("com.zyu.Person");
// 2. 新增一个字段 private String name;
// 字段名为name
CtField param = new CtField(pool.get("java.lang.String"), "name", cc);
// 访问级别是 private
param.setModifiers(Modifier.PRIVATE);
// 初始值是 "zyu"
cc.addField(param, CtField.Initializer.constant("zyu"));
// 3. 生成 getter、setter 方法
cc.addMethod(CtNewMethod.setter("setName", param));
cc.addMethod(CtNewMethod.getter("getName", param));
// 4. 添加无参的构造函数
CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);
cons.setBody("{name = "zyu";}");
cc.addConstructor(cons);
// 5. 添加有参的构造函数
cons = new CtConstructor(new CtClass[]{pool.get("java.lang.String")}, cc);
// $0=this / $1,$2,$3... 代表方法参数
cons.setBody("{$0.name = $1;}");
cc.addConstructor(cons);
// 6. 创建一个名为printName方法,无参数,无返回值,输出name值
CtMethod ctMethod = new CtMethod(CtClass.voidType, "printName", new CtClass[]{}, cc);
ctMethod.setModifiers(Modifier.PUBLIC);
ctMethod.setBody("{System.out.println(name);}");
cc.addMethod(ctMethod);
//这里会将这个创建的类对象编译为.class文件
cc.writeFile("D:\IdeaProjects\JavassistDemo\src\main\java");
// 这里不写入文件,直接实例化
// Object person = cc.toClass().newInstance();
// // 设置值
// Method setName = person.getClass().getMethod("setName", String.class);
// setName.invoke(person, "dadududu");
// // 输出值
// Method execute = person.getClass().getMethod("printName");
// execute.invoke(person);
}
说明
- 相较于ASM技术,Javassist技术提供了更多的API,减少了我们对指令的关心,相对来说更好用。