如何在Java中实现包装装饰器?

2023-11-26

问题是创建现有对象的动态增强版本。

我无法修改对象的Class。相反,我必须:

  • 子类化它
  • 将现有对象包装在新对象中Class
  • 将所有原始方法调用委托给包装对象
  • 实现另一个接口定义的所有方法

添加到现有对象的接口是:

public interface EnhancedNode {

  Node getNode();
  void setNode(Node node);

  Set getRules();
  void setRules(Set rules);

  Map getGroups();
  void setGroups(Map groups);

}

With 字节好友我设法子类化并实现我的接口。问题在于对包装对象的委托。我发现执行此操作的唯一方法是使用太慢的反射(我的应用程序负载很重,性能至关重要)。

到目前为止我的代码是:

Class<? extends Node> proxyType = new ByteBuddy()
     .subclass(node.getClass(), ConstructorStrategy.Default.IMITATE_SUPER_TYPE_PUBLIC)
     .method(anyOf(finalNode.getClass().getMethods())).intercept(MethodDelegation.to(NodeInterceptor.class))
     .defineField("node", Node.class, Visibility.PRIVATE)
     .implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
     .defineField("groups", Map.class, Visibility.PRIVATE)
     .implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
     .defineField("rules", Set.class, Visibility.PRIVATE)
     .implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
     .make()
     .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
     .getLoaded();
enhancedClass = (Class<N>) proxyType;
EnhancedNode enhancedNode = (EnhancedNode) enhancedClass.newInstance();
enhancedNode.setNode(node);

where Node是要子类化/包装的对象。这NodeInterceptor将调用的方法转发给getNode财产。

这里的代码是NodeInterceptor:

public class NodeInterceptor {

  @RuntimeType
  public static Object intercept(@Origin Method method,
                               @This EnhancedNode proxy,
                               @AllArguments Object[] arguments)
        throws Exception {
      Node node = proxy.getNode();
      Object res;
      if (node != null) {
          res = method.invoke(method.getDeclaringClass().cast(node), arguments);
      } else {
          res = null;
      }
      return res;
  }
}

一切正常,但拦截方法太慢,我打算直接使用ASM来添加Node每个方法的实现,但我希望有一种使用Byte Buddy的更简单的方法。


您可能想使用Pipe而不是反射 API:

public class NodeInterceptor {

  @RuntimeType
  public static Object intercept(@Pipe Function<Node, Object> pipe,
                                 @FieldValue("node") Node proxy) throws Exception {
      return proxy != null
        ? pipe.apply(proxy);
        : null;
  }
}

为了使用管道,您首先需要安装它。如果您有可用的 Java 8,您可以使用java.util.Function。否则,只需定义某种类型:

interface Function<T, S> { S apply(T t); }

你自己。类型的名称和方法是无关的。安装类型:

MethodDelegation.to(NodeInterceptor.class)
                .appendParameterBinder(Pipe.Binder.install(Function.class));

但是,您确定反射部分是应用程序性能问题的关键点吗?您是否正确缓存生成的类并且缓存是否有效工作?反射 API 比它的声誉更快,特别是因为使用 Byte Buddy 往往意味着单态调用站点。

最后,一些一般性反馈。你正在呼唤

.implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())

多次。这没有效果。还,method.getDeclaringClass().cast(node)没有必要。反射 API 会为您进行转换。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Java中实现包装装饰器? 的相关文章

  • Java - 将无符号十六进制字符串解析为有符号长整型

    我有一堆十六进制字符串 其中之一是 d1bc4f7154ac9edb 这是 3333702275990511909 的十六进制值 如果执行 Long toHexString d1bc4f7154ac9edb 这与您得到的十六进制相同 现在
  • 将 WAR 部署到 Tomcat(Spring Boot + Angular)

    我正在尝试使用以下命令部署 Spring Boot 应用程序WAR包装至Tomcat 10 应用程序已成功部署 但是 当我尝试访问端点时 它会导致404 未找到 战争文件 应用程序 war http localhost 8080 appli
  • 使用 TLS PSK 加密时如何正确检测流结束?

    我已经准备好了一个简单的 TLS PSK 客户端测试用例 https github com afarber jetty newbie tree master TlsPskClient2 src main java de afarber tl
  • 二元运算符 >=、-、* 的错误操作数类型

    我无法弄清楚如何修复代码中不断出现的这些错误 import java util Scanner public class Unit02Prog1 public static void main String args Scanner inp
  • JAX-WS 入门 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有人可以推荐一些关于 JAX WS 入门的好教程吗 使用各种工具 如 wsgen 等 您可以从这里开始 通过 Java SE 6 平台介绍
  • java中高效的输入流到字符串方法

    因此 我在 Java 中的 诚然非常简单 应用程序上运行探查器 令我惊讶的是 仅次于需要在时间上发出 HTTP 请求的方法的是我的方法 inputStreamToString方法 目前它的定义如下 public static String
  • 使用 Spring MVC 在 jar 文件中显示 jsp 页面

    我正在使用 Spring MVC 3 2 2 在 java 中开发一个 Web 应用程序 我在从 jar 文件中加载 jsp 页面时遇到问题 Spring MVC Web应用程序具有以下结构 META INF WEB INF spring
  • 如何杀死 Java Future?

    我正在开发的服务使用 Future 来并行运行多个任务 每个任务最多可能需要一分钟才能完成 然而 外部库似乎有问题 因为在某些情况下 2 的时间 它不会返回 在这些情况下 我想给出 2 分钟的等待时间 如果还没有返回 我想杀死 future
  • 是否可以创建 Java RAM 磁盘以与 java.io.* API 一起使用?

    我正在使用一个第三方库 它基本上创建一个输出目录 其中包含不同类型的文件和子目录 我希望能够编写单元测试来确认输出正确 我希望能够将库与 RAM 磁盘一起使用 这样库所做的任何事情都不会以任何方式接触实际的磁盘板 这个想法是让测试运行和清理
  • 生成一定长度的所有排列

    假设我们有一个字母表 abcdefghiklimnop 如何以有效的方式以五个一组的形式重复该字母表来递归生成排列 几天来我一直在为此苦苦挣扎 任何反馈都会有帮助 本质上这与 生成给定字符串的所有排列 https stackoverflow
  • JFrame 在连续运行代码时冻结

    我在使用时遇到问题JFrame 它会冻结 连续运行代码 下面是我的代码 点击时btnRun 我调用了该函数MainLoop ActionListener btnRun Click new ActionListener Override pu
  • java彩色滚动条搜索结果

    我将如何在 Java 中自定义滚动条 以便我可以进行像 chrome 一样的搜索 也就是说在结果所在的位置放置彩色条纹 我不想要一个库 因为我更喜欢自己编写代码 另外 我不想失去我拥有的 L F 欢迎举例 实际上 它将查看一个大的文本文件或
  • java绕中心旋转矩形

    我想围绕其中心点旋转一个矩形 它应该保留在应该绘制的位置并在该空间中旋转 这是我的代码 AffineTransform transform new AffineTransform transform rotate Math toRadian
  • 如何在 JmsMessagingTemplate.sendAndReceive 上设置等待超时

    我在 MVC 控制器中使用 JmsMessagingTemplate 的 sendAndReceive 但如果没有发送回复消息 它似乎会永远等待回复 该文档指出 返回 回复 如果无法接收消息 例如由于超时 则可能为 null 然而 我只是不
  • Spring Security 角色层次结构不适用于 Thymeleaf sec:authorize

    我正在使用 Spring Security 3 2 5 RELEASE 和 ThymeLeaf 2 1 4 RELEASE 我已经在安全上下文中定义了角色层次结构 在我的视图层中我正在使用sec authorize属性来定义菜单项 我希望看
  • Hybris:如何在impex中导入zip文件中的媒体?

    我知道我们可以导入未像这样压缩的图像 siteResource jar com project initialdata constants ProjectInitialDataConstants projectinitialdata imp
  • 如果 Modelmapper 中的整个属性为空,如何排除它们

    ModelMapper 是否 http modelmapper org http modelmapper org 支持什么排除属性 如果该值为空 我刚刚找到了 PropertyMap 但这对我来说是一种限制 因为我必须描述我想要的特定属性
  • 如何在不使用 -cp 开关的情况下在 Groovy 中自动加载数据库 jar?

    我想简化调用 Oracle 数据库的 Groovy 脚本的执行 如何将 ojdbc jar 添加到默认类路径以便我可以运行 groovy RunScript groovy 代替 groovy cp ojdbc5 jar RunScript
  • JPA ManyToMany 产生的空联接表

    我有一个应用程序 其中我尝试使用 Hibernate 作为 JPA 提供程序来实现两个实体之间的多对多关系 我正在尝试的例子是一个单向的 其中一个相机可以有多个镜头 而镜头可以安装到多个相机中 以下是我的实体类 只需粘贴其中的相关部分 Ca
  • Graphics2D setfont() 严重减慢了 java 应用程序的启动速度

    我正在用java制作一个游戏 它每秒刷新60次 每次执行循环时 我都会使用 g2d 来绘制图像和字符串 如果我这样做的话一切都会很好g2d setFont new Font Arial Font PLAIN 8 和抽绳 这将是正常的 但如果

随机推荐

  • 在 Wordpress XMLRPC 中附加图像以发布

    我正在使用 XMLRPC 向 Wordpress 发布帖子 我在发布缩略图时遇到问题 在调试 WordPress 代码后 我发现我的问题是由于图像未附加到帖子中而引起的 我必须在不修补 WordPress 或使用 PHP 的情况下执行此操作
  • Hibernate 和 JPA 有什么区别? [复制]

    这个问题在这里已经有答案了 当我在大学学习 Web 编程时 他们向我们介绍了 Hibernate 我们使用了一段时间 我什至有机会在公司的真实场景中使用它近 8 个月 现在我完全切换到 Java EE 6 我使用 JPA 来满足我的 ORM
  • WCF Duplex 客户端的最佳实践

    我不能否认双工异步调用的性能优势 但有些事情让我感到谨慎 我担心的是 给定一个实例化的客户端对象 WCF 是否能够知道哪个特定的客户端服务实例将接收回调参数 谁能告诉我这是否是一个好主意 如果不是为什么不呢 new DuplexChanne
  • 如何停止 http.ListenAndServe()

    我正在使用 Gorilla Web Toolkit 中的 Mux 库以及捆绑的 Go http 服务器 问题是 在我的应用程序中 HTTP 服务器只是一个组件 需要由我自行决定停止和启动 当我打电话时http ListenAndServe
  • QWidget::setLayout:尝试在主窗口“”上设置 QLayout“”,该窗口已经有布局

    我正在 PyQt4 中制作一个应用程序 这是迄今为止我的代码 import sys from PyQt4 import QtGui QtCore class MainWindow QtGui QMainWindow def init sel
  • 在 HTML 表中显示 JSON 数据

    我从服务器获取以下 JSON 字符串作为响应 city AMBALA cStatus Y city ASANKHURD cStatus Y city ASSANDH cStatus Y 这是我的 Jquery 代码 search click
  • 使用 lm 对象填充列表

    我正在尝试使用 R 中 OLS 的结果填充命名列表 我尝试过 li list for i in 1 10 li RunOne i lm y x Here RunOne是一个随机名称 指定拟合运行一个 y and x是一些预定义的向量 这会破
  • 如何在react组件中加载脚本

    我有以下脚本文件
  • 单独的“调试”和“发布”版本?

    我认为最好发布您的开发人员实际测试过的软件版本 因此 我倾向于从项目 makefile 中删除 调试 目标 这样就只能构建 并测试 调试和发布 一个版本 出于类似的原因 我不使用 断言 另请参阅断言总是不好的吗 那里的一个人认为 调试 版本
  • 后台附件:修复了在 Android/移动设备上无法工作的问题

    我正在开发一个科尔多瓦应用程序 我正在尝试获得固定的背景 不幸的是 它似乎不起作用 每当我向下滚动时 背景就会从页面顶部消失 这是我用来执行此操作的 CSS 并且我已经尝试了其他几种方法 html width 100 height 100
  • 如何使用 WatchService 监视子目录的更改? (爪哇)

    我想查看一些目录及其子目录的更改 我尝试这样做WatchService但我不知道文件是从哪个目录更改的 如何从中检索完整路径WatchEvent 通常 您在启动 watchservice 时提供文件的目录名称 这是一个演示其工作原理的教程
  • 如何阻止所有非美国 IP 地址访问我的网站?

    我想阻止所有非美国用户访问我的网站 我在前端使用 nginx 并有一个 django 支持的网站 1 如何确定什么是美国 IP 地址 2 我应该在我的网络服务器或应用程序层中阻止它们吗 你需要一个地理位置提供者 有些是免费的 有些是在线检查
  • Maven docker 缓存依赖项

    我正在尝试使用 docker 来自动化 Maven 构建 我想要构建的项目需要将近20分钟才能下载所有依赖项 因此我尝试构建一个可以缓存这些依赖项的docker镜像 但它似乎没有保存它 我的 Dockerfile 是 FROM maven
  • 捕获按键而不在页面上放置输入元素?

    如何在 JavaScript 中捕获按键 例如 Ctrl Z 而不在页面上放置输入元素 似乎在 IE 中 keypress 和 keyup 事件只能绑定到输入元素 输入框 文本区域等 对于不可打印的键 例如箭头键 和快捷键 例如 Ctrl
  • 在 OpenGL 中将纹理映射到球体时出现接缝问题

    我正在尝试创建几何体来在 OpenGL 中表示地球 我有一个或多或少的球体 虽然更接近地球的椭圆大地水准面 我绘制了地球表面的纹理 可能是墨卡托投影或类似的东西 纹理的 UV 坐标对应于几何体的纬度和经度 我有两个问题无法解决 我正在使用
  • 如何使用具有不同 URL 模式的单个 Servlet?

    我需要使用具有不同 URL 模式的单个 servlet 我已经在tomcat服务器中进行了尝试 如下所示 但我想知道真正的编码标准 请帮助我 String servletPath request getServletPath if Hell
  • React-router + typescript 类型错误

    在使用打字稿创建我的反应应用程序时 我遇到了一个我还无法解决的小问题 My code App tsx import as React from react import as ReactDOM from react dom import P
  • 如何自定义“hg commit”生成的“提交消息文件”?

    当我跑步时hg commit Mercurial 为我的提交消息生成一个文件 如下所示 HG Enter commit message Lines beginning with HG are removed HG Leave message
  • 在 PHPStorm 中,当我有一个从每个子类返回不同类型的超类方法时,如何使类型提示起作用

    我有一个从超类继承的类 并且超类具有静态find 实例化子类实例的方法 活动记录模式 class ActiveRecordClass return mixed public static function find Code returns
  • 如何在Java中实现包装装饰器?

    问题是创建现有对象的动态增强版本 我无法修改对象的Class 相反 我必须 子类化它 将现有对象包装在新对象中Class 将所有原始方法调用委托给包装对象 实现另一个接口定义的所有方法 添加到现有对象的接口是 public interfac