小工具      在线工具  汉语词典  css  js  c++  java

JDK动态代理

java,动态代理,java,Proxy 额外说明

收录于:40天前

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

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

JDK动态代理的实现示例:

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

用户服务

public interface IUserService {

public String getUserNameById(int uid);
}

用户服务实现:


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;
}
}

动态代理


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(加载器、接口、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接口中?

通过一堆调试,代理类中的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原生的代理机制来处理的。

@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

. . .

相关推荐

额外说明

mui混合开发-扫描二维码和条形码

方式一: .mask { height: 100%; width: 100%; position: absolute; top: 44px; /*background: rgba(0, 0, 0, 0.5);*/

额外说明

学通最新JS逆向分析

目标网址:https://passport2.chaoxing.com/login 重要说明:文章教程仅供参考学习,请勿用于非法用途,否则后果自负。 目录 一、接口请求参数分析 二、参数加密逻辑分析

额外说明

项目中如何使用缓存?缓存如果使用不当会产生什么后果?雷迪斯

    1、面试题 在项目中缓存是如何使用的?缓存如果使用不当会造成什么后果? 2、面试官心里分析 这个问题,互联网公司必问,要是一个人连缓存都不太清楚,那确实比较尴尬 只要问到缓存,上来第一个问题,肯定能是先问问你项目哪里用了缓存?为啥要用?不用行不行

额外说明

基于SpringBoot+Vue的宠物管理系统了解一下

您好,我是码农飞哥(wei158556),感谢您阅读本文,欢迎一键三连哦。 -- 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精通 - 2. 毕业设计专栏,毕业季咱们不慌忙,几百款毕业设计等你选。

额外说明

如何让VsCode自动格式化代码?

文章目录 一、展示格式混乱的代码 二、设置粘贴、保存时自动格式化代码 三、演示代码自动格式化 一、展示格式混乱的代码 虽然不影响程序运行结果,但是代码看着混乱不堪,如果手动格式化,那真是费事! 二、设置粘贴、保存时自动格式化代码 File - Prefe

额外说明

servlet过滤器入门

servlet API中最重要的一个功能就是能够为servlet和JSP页面定义过滤器。过滤器提供了某些早期服务器所支持的非标准“servlet链接”的一种功能强大且标准的替代品。                                     

额外说明

Java案例:数据表转换成XML文档

将数据表查询内容转换成XML文件,便于在网络上进行传输,具有一定的实用价值。   1、数据表(student) 2、数据库连接管理类 /** * 功能:获得数据库连接 * 作者:华卫 * 日期:2010年4月2日 */ package net.h

额外说明

Mybatis查树的两种写法

Mybatis查树必须会,它有两种写法: 1、联表查询。只访问一次数据库。 2、递归查询。访问多次数据库。 1、联表查询(推荐) 表结构: create table common_region ( region_id int(11), pr_regi

额外说明

软考 系统架构设计师 高分通过的经验和心得

自从考试成绩公布以来,我一直想分享一下我备考的经验和心得。然而,我的拖延症让我总是耽搁着没有写下来。 这次考试对我的挑战可谓不小,但我还是尽力而为,经过了充分的备考和思考,终于高分通过了,如下图: 我想简单科普一下这次考试的科目:综合知识、案例分析和论文

额外说明

解决Windows系统找不到dx7vb.dll文件出现错误问题

其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个dx7vb.dll文件(挑选

ads via 小工具