JDK动态代理

代理的概念.
这里写图片描述

代理类和实现类,都会实现同样的接口. 但是,动态代理有点不同,即,此代理类不是显式的,而是动态的,具体来讲,这个proxy是后续生成的。
要实现动态代理,就要生成一个新的类,这种方式并不常规,
我主要知道的动态的代理实现有:
1, AspectJ,这是在编译过程中新增的类,且使用的是需要第三方编译工具.
2,JDK动态代理
这篇文章是介绍jdk动态代理来.

JDK动态代理的实现例子:

一共四个类:
IUserService 接口类
UserServiceImpl 实现类,被代理的类
InvoHandlerImpl 理解为代理类
DynamicProxy main函数的类

IUserService

public interface IUserService {

public String getUserNameById(int uid);
}

UserServiceImpl:


public class UserServiceImpl implements IUserService{

@Override
public String getUserNameById(int uid) {
System.out.println("正在执行getUserNameById");
if (uid > 0) {
return "张三";
}
return "李四";
}
}

InvoHandlerImpl

public class InvoHandlerImpl implements InvocationHandler
{
/**
* 被代理对象
*/
private Object subject;

public InvoHandlerImpl(Object subject)
{
    this.subject = subject;
}

/**
* 这个方法会被 生成的代理对象执行
* 调用方法时具体执行的逻辑
* 里面加上before和after
* @param proxy 代理对象
* @param method 被调用方法
* @param args 被调用方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
    System.out.println("方法前逻辑,方法"+method);
    //执行具体的逻辑
    Object returnValue = method.invoke(subject, args);
    System.out.println("方法后逻辑");
    return returnValue;
}
}

DynamicProxy


public class DynamicProxy {

public static void main(String args[]){


IUserService userService = new UserServiceImpl();

InvoHandlerImpl invoHandler = new InvoHandlerImpl(userService);
ClassLoader loader = userService.getClass().getClassLoader();
Class[] interfaces = userService.getClass().getInterfaces();

IUserService targetService = (IUserService) Proxy.newProxyInstance(loader, interfaces, invoHandler);

System.out.println(targetService.getUserNameById(100));

}
}

上面的main函数,核心是 Proxy.newProxyInstance(…), 此方法后则返回了一个代理类

相关源码分析:

查看InvoHandlerImpl的invoke方法可知,实际是用反射机制来处理的.
当一个方法在调用的时候,通过反射机制把其Method对象取出来,然后前后加下切面逻辑后再执行这个method,则可以达到切面的效果。

  • Proxy.newProxyInstance(loader, interfaces, invoHandler); 这一行做了什么?

结果来看,是生成一个Proxy类对象,同时这个类实现了IUserService接口

/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, interfaces);

这一句就是通过接口生成一个设计好的代理类.在这里还没有把invoke加上去,只是生成了一个proxy类。
我们可以发现proxy类里有一个构造方法有invoke入参的,只有有这个proxy类,则调用这个构造方法,就可以返回有invoke的对象。对应的代码:

final Constructor<?> cons = cl.getConstructor(constructorParams); //  constructorParams是写死的InvocationHandler.class`
....
return cons.newInstance(new Object[]{h});
  • 怎么样把Proxy类加上iuserService接口的?

通过一堆debug,proxy类中 apply方法的这一段

/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);

三个参数,一个是代理的名称,一个是接口集
至于里面是怎么实现的,都以二进制来搞了,我就没有深入进去了,既然是byte[],应该可以打印到文件,然后来查看。总之 ProxyGenerator.generateProxyClass 这修正方法是可以直接生成代理类的。

  • 代理类执行getUserById方法是什么情况

这里写图片描述

  • spring的aop也是用jdk来实现了

从上面的方法可知,生成一个代理类是生成二进制的方式来做的,spring 既然要动态生成,也是需要用到这种机制了.

以下org.springframework.aop.framework.JdkDynamicAopProxy这个类的getProxy方法,可知spring 也是用jdk原生的proxy机制来处理的。

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

spring 的aop需要进一步研究,现在是看到有相应的代码关联,不确认有没有其它方式.,而且现在的spring的aop不一定要接口,这也是需要后续查看的.

参考:

https://blog.csdn.net/jiankunking/article/details/52143504

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值