JDK动态代理的实现原理
1、根据传入的类的接口和InvocationHandler为接口创建代理类的字节码文件。通过反射创建method。method就是接口里面的方法,通过method就可以调用实现类重写的方法。
2、使用ClassLoader将字节码文件加载到JVM(定义了一个类,类似于$Proxy0、$Proxy1之类的)
3、通过反创建代理类实例对象
4、当调用代理对象方法时,就会进入到InvocationHandler的invoke方法中,这里就是用户编写的代理逻辑。通过method.invoke调用被代理对象的实现逻辑。
通过反射生成method,然后定义一个ProxyX的类,然后反射实例化这个类生成代理对象。代理对象的方法都会进入InvocationHandler的invoke方法
ps:jdk代理只能代理接口里面实现的类以及equals、hashCode、toString方法。
jdk代理不支持对实现类的代理,只支持接口的代理,因为生成的类已经继承了Proxy,java不能多继承。
https://blog.csdn.net/mhmyqn/...
cglib的实现代理的逻辑。
1、首先我们通过Enhancer实例设置被代理类,
2、然后设置该代理类的回调,也就是在访问代理类方法的时候会首先转向该回调,
3、在回调中我们调用invokeSuper方法以fastclass这种非反射机制快速的调用到代理类中的方法,其中代理类中方法又调用原类型的对应方法。
methodProxy.invokeSuper(Object obj, Object[] args)-->根据方法名生成fastClassInfo,然后根据fastClassInfo中下标信息直接调用fastclass的invoke方法。根据obj的类型进入对应的fastclass
目标类的fastclass的 invoke方法
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
// 直接强转
UserManagerImpl var10000 = (UserManagerImpl)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.delUser((String)var3[0]);
return null;
case 1:
...
...
代理类的fastclass的 invoke方法
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
326ab821 var10000 = (326ab821)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return new Boolean(var10000.equals(var3[0]));
case 1:
...
...
总结一下JDK动态代理和Gglib动态代理的区别:
1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
2.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
3.JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。注意:只有invokeSuper才是fastClass机制,其余的invoke还是用的反射
https://www.cnblogs.com/monke...
通过Enhancer可以生成代理类,传入CallBack使代码执行时进入CallBack代码中,从而执行用户自定义代码;
用户自定义代码可以决定使用目标类调用还是代理类调用
目标类使用$$FastClass1进行调用
代理类使用$$FastClass2进行调用
$$FastClass都在调用时触发生成
$$FastClass为动态生成类,通过index与方法签名一一映射产生switch case 语句来提高调用效率
代理类是通过继承方式实现,不能对final类和方法使用CGLIB代理。
因此 CGLB代理调用效率高,但是生成效率慢,至少3个文件,1个代理类,2个FastClass类。所有生成的类都会加载到JVM堆中。
package proxy;
public class BigCar implements Car{
@Override
public void start() {
System.out.println("big car start");
}
public void start(int a) {
System.out.println("big car start");
}
}
package proxy;
public interface Car {
void start();
}
package proxy;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibInvocationHandler implements MethodInterceptor {
Object target;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
/**
调用过程:
代理对象调用 this.被代理的方法
->调用拦截器intercept
->methodProxy.invokeSuper
->CGLIB$setPerson$0
->被代理对象setPerson方法
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib proxy start");
// o是代理对象,methodProxy.invoke会调用o的方法,然后再进入intercept方法会形成死循环
Object result = methodProxy.invokeSuper(o, objects);
// 原生cglib可以实现内部方法代理,
// spring的cglib实现的aop不能切到内部调用的方法,除非特意设置
// spring aop的写法
// spring 会保存真实对象的 bean 。
// Object result = methodProxy.invoke(target, objects);
System.out.println("cglib proxy end");
return result;
}
}
package proxy;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
public class CglibProxyFactory {
public static Object createProxy(Class c,Callback callback){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(c);
enhancer.setCallback(callback);
return enhancer.create();
}
}
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class JdkProxyFactory {
public static Object getJDKProxy(Object targetObject, InvocationHandler handler) {
// JDK动态代理只能针对实现了接口的类进行代理,newProxyInstance 函数所需参数就可看出
// 根据接口类
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
handler);
}
}
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//JDK动态代理实现InvocationHandler接口
public class JdkProxyInvocationHandler implements InvocationHandler {
private Object target;//需要代理的目标对象
public JdkProxyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK动态代理,监听开始!");
System.out.println(proxy.getClass()+" 111");
Object result = method.invoke(target, args);
System.out.println("JDK动态代理,监听结束!");
return result;
}
}
package proxy;
import net.sf.cglib.core.DebuggingClassWriter;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
UserManager target = new UserManagerImpl();
// JdkProxyInvocationHandler handler = new JdkProxyInvocationHandler(target);
// UserManager userManager = (UserManager) JdkProxyFactory.getJDKProxy(target, handler);
// userManager.addUser("1", "1");
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\Users\\YEZHENGWU839\\Desktop\\xiaoxi");
CglibInvocationHandler handler1 = new CglibInvocationHandler();
handler1.setTarget(target);
UserManager userManager2 = (UserManager) CglibProxyFactory.createProxy(target.getClass(), handler1);
userManager2.addUser("2","@");
System.out.println(userManager2.getClass().getName());
}
}
package proxy;
public interface UserManager {
//新增用户抽象方法
void addUser(String userName, String password);
//删除用户抽象方法
void delUser(String userName);
default void find(){
System.out.println("super interface find");
}
}
package proxy;
//用户管理实现类,实现用户管理接口
public class UserManagerImpl implements UserManager {
//重写新增用户方法
@Override
public void addUser(String userName, String password) {
System.out.println("调用了新增的方法!");
System.out.println("传入参数为 userName: " + userName + " password: " + password);
delUser("111");
}
//重写删除用户方法
@Override
public void delUser(String userName) {
System.out.println("调用了删除的方法!");
System.out.println("传入参数为 userName: " + userName);
}
// 不是接口的类 没办法代理
public void show() {
System.out.println("this impl method not super method");
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。