栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

动态代理模式面试题(动态代理模式应用)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

动态代理模式面试题(动态代理模式应用)

jdk动态代理
通过拼接java代码,编译成class文件,生成的文件实现接口中的每一个方法,通过调用方法,实现拦截.调用InvocationHandler.invoke
方法实现代理逻辑.

public class JdkInvocationHandler implements InvocationHandler {
	private Object target;

	public JdkInvocationHandler(OredrServiceImpl impl) {
		this.target = impl;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println(">>jdk动态代理执行开始<<");
		Object obj = method.invoke(target, args);
		System.out.println(">>jdk动态代理执行结束<<");
		return obj;
	}
	
	public  T getProxy() {
		
		return (T)
				Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
}

OredrService orderService = getProxy() 生成OrderService的代理类

public class $Proxy0 implements OrderService {

	private InvocationHandler h;

	private static Method m1;
	private static Method m2;
	private static Method m3;
	private static Method m0;

	private $Proxy0(InvocationHandler invocationHandler) {
		this.h = invocationHandler;
	}

	@Override
	public void addOrder(String var1, String var2) throws Throwable {
		this.h.invoke(this, m3, new Object[]{var1, var2});

	}


	static {
		try {
			m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
			m3 = Class.forName("test01.proxy.entity.OrderService").getMethod("addOrder", Class.forName("java.lang.String"), Class.forName("java.lang.String"));
			m2 = Class.forName("java.lang.Object").getMethod("toString");
			m0 = Class.forName("java.lang.Object").getMethod("hashCode");
		} catch (NoSuchMethodException var2) {
			throw new NoSuchMethodError(var2.getMessage());
		} catch (ClassNotFoundException var3) {
			throw new NoClassDefFoundError(var3.getMessage());
		}
	}
}


当调用orderService.addOrder 
实际上是调用代理类中addOrder方法
this.h 就是newProxyInstance时候传入的this
然后调用jdk的反射,反射式target调用的这里很关键,因为他不式代理类,注解不管用



cglib
利用asm编码直接编辑的class文件,利用索引去调用的方法.他是继承实现类,
他会生成三个文件.一个代理类(实现被代理的实现类,并重写里边所有的方法,并且添加自己的代理方法)
两个索引方法,继承FastClass
生成的代理类,会为每个代理方法创建个MethodProxy(
其中记录代理类和被代理类的class
放回值+参数
被代理的方法
代理的方法)

CGLIB$addMember$0$Proxy = 
MethodProxy.create(var1, var0, "(Ljava/lang/String;)Ljava/lang/String;", "addMember", "CGLIB$addMember$0");

当调用

    public final String addMember(String var1) {
        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$addMember$0$Method, new Object[]{var1}, CGLIB$addMember$0$Proxy) : super.addMember(var1);
    }

var10000.intercept(this, CGLIB$addMember$0$Method, new Object[]{var1}, CGLIB$addMember$0$Proxy)
var10000 是实现MethodInterceptor  callback的方法



public class MethodProxy {
    private Signature sig1;  //被代理的方法
    private Signature sig2;	//生成的代理方法
    private MethodProxy.CreateInfo createInfo;
    
    
    private final Object initLock = new Object();
    private volatile MethodProxy.FastClassInfo fastClassInfo;
	

}
```javascript
public class CglibMethodInterceptor implements MethodInterceptor {
	
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		System.out.println(">>cglib动态代理执行开始<<");
		Object result = proxy.invokeSuper(obj, args);
		System.out.println(">>cglib动态代理执行结束<<");
		return result;
	}
}

需要注意的是
proxy是传入的CGLIB$addMember$0$Proxy


proxy.invokeSuper(obj, args);
执行的时候

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        try {
            this.init();
            MethodProxy.FastClassInfo fci = this.fastClassInfo;
            return fci.f2.invoke(fci.i2, obj, args);
        } catch (InvocationTargetException var4) {
            throw var4.getTargetException();
        }
    }


这里的f2是代理类的索引类
i2则是代理的方法的索引
invoke 调用的是代理类的索引类方法

 public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        232fdf0b var10000 = (232fdf0b)var2;// 强转为 CGLIB$addMember$0$Method( intercept 方法穿的是this)
        int var10001 = var1;
        case 16:
                return var10000.CGLIB$addMember$0((String)var3[0]);




final String CGLIB$addMember$0(String paramString) {
		return super.addMember(paramString); // 调用原来impl 的方法
	}

注意的是:
生成的的代理都不继承注解的,注解会失效的具体情况具体分析:

controller 中的方法有aop注解方法则会失效,因为执行方法的不是代理类

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/775539.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号