JDK动态的代理:
https://blog.csdn.net/P19777/article/details/103998918
先来一个大致的机制介绍,后面是详细的:
生成一个代理类实现了被代理类的接口,代理类实现目标方法,方法中会调用InvocationHandler 实现类的invoke方法;
大家都会的无脑使用方式,简单写个demo
1、定义一个接口:
package com.bijian.proxy;
public interface UserService {
void update();
}
2、定义一个实现 类
package com.bijian.proxy;
public class UserServiceImpl implements UserService {
@Override
public void update() {
System.out.println("执行目标方法...");
}
}
3、定义一个动态代理生产的类:这也是最重要的
package com.bijian.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler {
/**
* 目标类
*/
private Object target;
public JDKProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK动态代理前置通知 method=" + method.getName() + " args=" + args);
Object invoke = method.invoke(target, args);
System.out.println("JDK动态代理后置通知method=" + method.getName() + " args=" + args);
return invoke;
}
public Object getProxy() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
JDKProxy proxy = new JDKProxy(new UserServiceImpl());
UserService userService =(UserService) proxy.getProxy();
userService.update();
}
}
机制分析
生成一个代理类,这个代理类实现了被代理类的接口;重写了其增强的方法,以上面的demo为例,会重写其update方法;接下来直接上生成的代理类代码:
package com.sun.proxy;
import com.bijian.proxy.UserService;
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 UserService {
private static Method m1;
private static Method m2;
private static Method m0;
private static Method m3;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void update() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m3 = Class.forName("com.bijian.proxy.UserService").getMethod("update");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
这一步获取的生成的代理对象也就是UserService userService =(UserService) proxy.getProxy();
点开源码,其中这一步 Class<?> cl = getProxyClass0(loader, intfs);就是生成代理类的class文件和class对象的;传参为被代理对象的类加载器和接口的class对象,返回代理类的class对象,然后cons.newInstance(new Object[]{h})利用反射技术创建代理类对象,传参为我们实现了 InvocationHandler接口的JDKProxy 对象;
当执行userService.update();方法时其实是执行的是代理类中的方法:
public final void update() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
其中super.h.invoke(this, m3, (Object[])null);也就是调用JDKProxy 中重写的方法:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK动态代理前置通知 method=" + method.getName() + " args=" + args);
Object invoke = method.invoke(target, args);
System.out.println("JDK动态代理后置通知method=" + method.getName() + " args=" + args);
return invoke;
}
传参为:第一参数为当前代理对象,第二个参数为目标方法对象,第三个参数为目标方法的参数数组对象;因为执行目标方法使用反射技术执行的,所以效率没有CGLB代理的高。
接着进入创建代理对象的的方法中:
Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
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);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
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) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
CGLB动态代理:
概述:动态代理是生成一个代理类继承被代理类,重写其每个方法;通过获取代理类来调用代理类中重写了目标方法的方法;
先上一个小白就会写的demo:
被代理类
package com.bijian.proxy;
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* jdk代理:
* 会生成
* 这里非常坑的是invoke方法和invokeSuper的区别,
* 如果是用invoke方法一定要使用被代理的对象也就是上文中的target,
* 而如果调用invokeSuper方法,则一定要使用被代理后的o对象。
*后面从源码角度分析
*/
public class CglibProxy implements MethodInterceptor {
private Object target;
public CglibProxy(Object target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("CGLP代理方面名=" + method.getName() + "前置通知");
Object invoke = methodProxy.invokeSuper(o, objects);
System.out.println("CGLP代理方面名=" + method.getName() + "后置通知");
return invoke;
}
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(this.target.getClass());
return enhancer.create();
}
public static void main(String[] args) {
System.getProperties().put(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:\\workspace\\spring-ioc-demo\\spring-framework-5.2.9.RELEASE\\my-spring-test\\src\\main\\java\\com\\bijian\\proxy");
CglibProxy cglibProxy = new CglibProxy(new UserServiceImpl());
UserService userServiceProxy =(UserService) cglibProxy.getProxy();
userServiceProxy.update();
}
}
机制分析:
在执行main方法时会生成三个代理类:
这三个类是enhancer.create()这一步产生的,我也没有具体看里面的代码
FastClass机制
Jdk动态代理的拦截对象是通过反射的机制来调用被拦截实例方法的,反射的效率比较低,所以cglib采用了FastClass的机制来实现对被拦截方法的调用。FastClass机制就是对一个类的方法建立索引,调用方法时根据方法的签名来计算索引,通过索引来直接调用相应的方法
生成的代理类介绍:
图片中中间的是生成的代理类,另外两个类是为代理类和原始类生成的fastClass机制的类;都是继承了FastClass这个类,其中一个是为生成的代理类中每个方法建立了索引,另一个类是为被代理类中每个方法建立了索引。
先看一下被代理类FastClass机制类:
有一个通过方法签名获得方法索引的方法;
还有一个通过索引和被代理对象和方法参数,执行目标方法的方法
package com.bijian.proxy;
import java.lang.reflect.InvocationTargetException;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.reflect.FastClass;
public class UserServiceImpl$$FastClassByCGLIB$$ff2de1c extends FastClass {
public UserServiceImpl$$FastClassByCGLIB$$ff2de1c(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -1949253108:
if (var10000.equals("update()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 int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 2;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 1;
}
}
}
break;
case -838846263:
if (var1.equals("update")) {
switch(var2.length) {
case 0:
return 0;
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 3;
}
}
}
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 {
UserServiceImpl var10000 = (UserServiceImpl)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.update();
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");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
UserServiceImpl var10000 = new UserServiceImpl;
UserServiceImpl 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 3;
}
}
看看生成的代理类:
以update()方法为例:
在静态代码块中会给代理中的
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
属性进行赋值,也就是我们实现的拦截器对象赋值到属性中;
看一下重写的目标方法:
public final void update() {
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$update$0$Method, CGLIB$emptyArgs, CGLIB$update$0$Proxy);
} else {
super.update();
}
}
获取到拦截器对象,执行拦截器中public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)我们实现的方法,
传参为当前代理对象、目标方法对象、方法参数列表、初始化的MethodProxy对象;
package com.bijian.proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
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$$dd0048a7 extends UserServiceImpl 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$update$0$Method;
private static final MethodProxy CGLIB$update$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.bijian.proxy.UserServiceImpl$$EnhancerByCGLIB$$dd0048a7");
Class var1;
CGLIB$update$0$Method = ReflectUtils.findMethods(new String[]{"update", "()V"}, (var1 = Class.forName("com.bijian.proxy.UserServiceImpl")).getDeclaredMethods())[0];
CGLIB$update$0$Proxy = MethodProxy.create(var1, var0, "()V", "update", "CGLIB$update$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$update$0() {
super.update();
}
public final void update() {
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$update$0$Method, CGLIB$emptyArgs, CGLIB$update$0$Proxy);
} else {
super.update();
}
}
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 -1949253108:
if (var10000.equals("update()V")) {
return CGLIB$update$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 UserServiceImpl$$EnhancerByCGLIB$$dd0048a7() {
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;
}
/**
* CGLIB$BIND_CALLBACKS 先从CGLIB$THREAD_CALLBACKS(一个ThreadLocal对象)中getCallback
* 如果获取不到的话,再从CGLIB$STATIC_CALLBACKS来获取,如果也没有则认为该方法不需要代理。
* 那么CallBack是如何设置到CGLIB$THREAD_CALLBACKS 或者 CGLIB$STATIC_CALLBACKS中的呢?
* 在Jdk动态代理中拦截对象是在实例化代理类时由构造函数传入的
* 在cglib中我们使用Enhancers生成代理类时。是调用Enhancer的firstInstance方法来生成代理类实例并设置回调。
* firstInstance的调用轨迹为:
1.Enhancer:firstInstance
2.Enhancer:createUsingReflection
3.Enhancer:setThreadCallbacks
4.Enhancer:setCallbacksHelper
5.Target$$EnhancerByCGLIB$$788444a0 : CGLIB$SET_THREAD_CALLBACKS
* 最终CGLIB实例化代理对象的时候,就在这里将所有的Callback成功设置了
*/
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 var1 = (UserServiceImpl$$EnhancerByCGLIB$$dd0048a7)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);
UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$dd0048a7();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$dd0048a7();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$dd0048a7;
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();
}
}
CGLIB$STATICHOOK1()这个静态方法内执行了MethodProxy.create()方法,为被代理所有的方法都生成了对应的MethodProxy,在调用代理对象的每个方法是都会有一个对应的MethodProxy就会当参数被传递到MethodInterceptor.intercept()方法中,在intercept中就能利用MethodProxy类的方法,使用FastClass机制
MethodProxy中的部分方法:
/**
* 一个MethodProxy对象,包含了两个方法的名称,一个是被代理类中的原始方法
* 另外一个则是代理类中生成的用来调用被代理类原始方法的方法名
* 当执行MethodProxy.invoke()方法时,其实就是用的被代理类的方法索引
* 当执行MethodProxy.invokeSuper()方法时,用的是代理类中的方法的索引
*
* c1是被代理类的class,也就是com.bijian.proxy.UserServiceImpl
* c2是代理类的class
* name1是被代理类中的原始方法名(也就是代理类中的重写的方法名)
* name2是代理类中新增的用来调用被代理类原始方法的方法的名字
这个类中的属性:sig1 为原始的方法签名 sig2为代理类中中新增的用来调用被代理类原始方法的方法签名
*/
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
MethodProxy proxy = new MethodProxy();
// Signature是用来标识一个唯一的方法
// 该标识可以用来获取fastClass中每一个方法的索引
proxy.sig1 = new Signature(name1, desc);
proxy.sig2 = new Signature(name2, desc);
proxy.createInfo = new CreateInfo(c1, c2);
return proxy;
}
private void init()
{
/*
* Using a volatile invariant allows us to initialize the FastClass and
* method index pairs atomically.
*
* Double-checked locking is safe with volatile in Java 5. Before 1.5 this
* code could allow fastClassInfo to be instantiated more than once, which
* appears to be benign.
*/
if (fastClassInfo == null)
{
synchronized (initLock)
{
if (fastClassInfo == null)
{
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
// helper中生成了对应Class的FastClass实例,这里可以看出就是生成了两个Class的FastClass
// f1为被代理类的class,也就是com.bijian.proxy.UserServiceImpl的的FastClass对象;f2为代理类的FastClass实例
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
// 获取方法的下标,sig1原本的方法名,sig2是为了调用父类方法生成的特殊方法的方法名
// i1为被代理类的目标方法索引下标, i2为代理类中的调用父类方法生成的特殊方法的索引下标
fci.i1 = fci.f1.getIndex(sig1);
fci.i2 = fci.f2.getIndex(sig2);
// 存储在本地变量上
fastClassInfo = fci;
createInfo = null;
}
}
}
}
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
// 调用init方法,当前MethodProxy就是代理类中初始化的,创建步骤上面已经说过
init();
FastClassInfo fci = fastClassInfo;
// 这里的f2就是一个FastClass,fci.i2就是在init方法中计算出来的索引:代理类中的调用父类方法生成的特殊方法的索引下标;所以Object obj必须穿代理类对象;不然会报错;
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
init();
// 这里的f1就是一个FastClass; fci.i1为被代理类的目标方法索引下标 ,这里的obj穿被代理类对象,否则会报错;栈内存溢出,如果穿的是代理类,则会执行代理类中重写的目标方法,无线循环调用
FastClassInfo fci = fastClassInfo;
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;
}
}
private static class FastClassInfo
{
// 被代理类的FastClass
FastClass f1;
// 代理类的FastClass
FastClass f2;
int i1;
int i2;
}