将代理附加到现有对象?

2024-03-15

我的计划是编写一个基于注释的缓存框架,用于缓存方法的返回值。当第一次使用特定参数调用方法时,缓存应该存储方法的返回值。 当使用相同的参数第二次调用相同的方法时,该方法应该从缓存中返回先前计算的结果,并且不再执行其代码。 我的注释如下所示:

@Cached(cacheProvider = HashMapCacheProvider.class)
public Product getProduct(String productId){    
    // Scraping the product from a website ...
    return product;
}

目前我的小框架已经运行良好。我正在使用 Javassist 创建包含带注释方法的类的代理对象。 为了创建一个新的缓存对象,我使用以下代码:

public static <T> T newCachedInstance(Class<T> clazz)
    throws InstantiationException, IllegalAccessException {

    ProxyFactory factory = new ProxyFactory();
    factory.setSuperclass(clazz);
    factory.setFilter(new MethodFilter() {
        public boolean isHandled(Method m) {
            // ignore finalize()
            return !m.getName().equals("finalize");
        }
    });

    Class<T> c = factory.createClass();

    T proxy = c.newInstance();
    ((ProxyObject) proxy).setHandler(new CachedMethodHandler());
    return proxy;
}

问题是,我只能通过此方法创建新的缓存对象,而不是通过其类的构造函数。 因此,我正在寻找一种解决方案,将现有的对象附加到缓存机制。

这是我的问题: 是否可以将代理附加到现有对象? 根据我的理解,如果不更新对此对象的所有现有引用,这应该是不可能的。

我的另一种方法是使用字节码操作来操作带注释的方法的代码,如下所示:

public class Hello {
    public void say() {
         System.out.println("Hello");
    }
}

public class Test {
    public static void main(String[] args) throws Exception {
        ClassPool cp = ClassPool.getDefault();
        CtClass cc = cp.get("Hello");
        CtMethod m = cc.getDeclaredMethod("say");
        m.insertBefore("{ System.out.println(\"Hello.say():\"); }");
        Class c = cc.toClass();
        Hello h = (Hello)c.newInstance();
        h.say();
    }
}

你还有其他想法吗?操作现有对象的方法的最佳实践是什么?


在默认的 Java 虚拟机中,每个对象实例都存储在堆中,其中其字段数据与其引用一起存储Class(以及用于垃圾收集的小区域)。您基本上是在问是否可以重新定义此链接以指向另一个链接Class默认情况下不可能的事情。

然而,你可以假设地 use sun.misc.Unsafe只要子类没有引入新字段,就可以用子类覆盖此引用。然而,其结果尚未定义,我不建议尝试它,因为框架的用户可能会遇到非常微妙的错误。另外,sun包层次结构不适合公共使用,这可能会破坏兼容性。

Attach API 提供了另一种方法。您可以使用 Java 代理在运行时重新定义类。然而,这会影响类的所有实例,但从您的目的来看,这是有意义的。

另一种可能性是使用 AspectJ 之类的东西在运行前重新定义类。

否则,您必须返回一个作为缓存代理的新实例,因为您显然已经这样做了。这绝对没问题,并且是 Hibernate 等主要框架使用的方法。请注意,javassist 比 cglib 慢得多,因为它直接读取类文件而不是使用反射访问以避免类加载。这可能会影响使用缓存时的性能。

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

将代理附加到现有对象? 的相关文章

  • Spring Security 自定义过滤器

    我想自定义 Spring security 3 0 5 并将登录 URL 更改为 login 而不是 j spring security check 我需要做的是允许登录 目录并保护 admin report html 页面 首先 我使用教
  • Java:无法从同一包中的不同类访问静态变量

    这很奇怪 因为我有一个可以访问 Frame dimension getWidth 的 Character 类 及其伙伴 getHeight 但是当我想在 Map 类中使用它时 Eclipse 强调了它并且无法给我反馈 运行该程序最终会出现
  • 如何在 Firebase 远程配置中从 JSON 获取值

    我是 Android 应用开发和 Firebase 的新手 我想知道如何获取存储在 Firebase 远程配置中的 JSONArray 文件中的值 String 和 Int 我使用 Firebase Remote Config 的最终目标是
  • 使用 Ant 将非代码资源添加到 jar 文件

    我正在将 java 应用程序打包成 jar 文件 我正在使用 ant 和 eclipse 我实际上需要在 jar 中直接在根文件夹下包含几个单独的非代码文件 xml 和 txt 文件 而不是与代码位于同一位置 我正在尝试使用includes
  • 打印星号的 ASCII 菱形

    我的程序打印出这样的钻石 但只有当参数或菱形的每一面为4 例如如果我输入6 底部三角形的间距是错误的 我一直在试图找出答案 当参数改变时 底部的三角形不会改变 只有顶部的三角形会改变 它只适用于输入4 public static void
  • Spring RestTemplate 使用 cookie 遵循重定向

    最近我遇到了一个问题 我需要做一个GET请求远程服务 我假设使用一个简单的 servlet 并且 RestTemplate 返回Too many redirects 经过一番调查 似乎对指定远程服务发出的第一个请求实际上只是一个 302 重
  • 是否可以使用 Flying Saucer (XHTML-Renderer) 将 css 解析为类路径资源?

    我正在尝试将资源打包到 jar 中 但我无法让 Flying Saucer 在类路径上找到 css 我无法轻松构建 URL 来无缝解决此问题 https stackoverflow com questions 861500 url to l
  • 如何根据运行的 jar 的结果让我的 ant 任务通过或失败?

    我正在运行 CrossCheck 无浏览器 js 单元测试 作为 ant 脚本的一部分 如果 CrossCheck 测试失败 我希望 ant 报告失败 这是 build xml 中的相关部分
  • Spring Security SAML2 使用 G Suite 作为 Idp

    我正在尝试使用 Spring Security 5 3 3 RELEASE 来处理 Spring Boot 应用程序中的 SAML2 身份验证 Spring Boot 应用程序将成为 SP G Suite 将成为 IDP 在我的 Maven
  • 需要使用 joda 进行灵活的日期时间转换

    我想使用 joda 解析电子邮件中的日期时间字符串 不幸的是我得到了各种不同的格式 例如 Wed 19 Jan 2011 12 52 31 0600 Wed 19 Jan 2011 10 15 34 0800 PST Wed 19 Jan
  • 自动生成Flyway的迁移SQL

    当通过 Java 代码添加新模型 字段等时 JPA Hibernate 的自动模式生成是否可以生成新的 Flyway 迁移 捕获自动生成的 SQL 并将其直接保存到新的 Flyway 迁移中 以供审查 编辑 提交到项目存储库 这将很有用 预
  • 在另一个模块中使用自定义 gradle 插件模块

    我正在开发一个自定义插件 我希望能够在稍后阶段将其部署到存储库 因此我为其创建了一个独立的模块 在对其进行任何正式的 TDD 之前 我想手动进行某些探索性测试 因此 我创建了一个使用给定插件的演示模块 到目前为止 我发现执行此操作的唯一方法
  • 如何在 Spring 属性中进行算术运算?

  • 内部存储的安全性如何?

    我需要的 对于 Android 我需要永久保存数据 但也能够编辑 并且显然是读取 它 用户不应访问此数据 它可以包含诸如高分之类的内容 用户不得对其进行编辑 我的问题 我会 并且已经 使用过Internal Storage 但我不确定它实际
  • HashMap 值需要不可变吗?

    我知道 HashMap 中的键需要是不可变的 或者至少确保它们的哈希码 hashCode 不会改变或与另一个具有不同状态的对象发生冲突 但是 HashMap中存储的值是否需要与上面相同 为什么或者为什么不 这个想法是能够改变值 例如在其上调
  • 使用布尔值进行冒泡排序以确定数组是否已排序

    我有以下用于冒泡排序的代码 但它根本不排序 如果我删除布尔值那么它工作正常 我知道 由于我的 a 0 小于所有其他元素 因此没有执行交换 任何人都可以帮助我解决这个问题 package com sample public class Bub
  • 是否可以使用 Java Guava 将函数应用于集合?

    我想使用 Guava 将函数应用于集合 地图等 基本上 我需要调整 a 的行和列的大小Table分别使所有行和列的大小相同 执行如下操作 Table
  • 洪水填充优化:尝试使用队列

    我正在尝试创建一种填充方法 该方法采用用户指定的初始坐标 检查字符 然后根据需要更改它 这样做之后 它会检查相邻的方块并重复该过程 经过一番研究 我遇到了洪水填充算法并尝试了该算法 它可以工作 但无法满足我对 250 x 250 个字符的数
  • 在java中使用多个bufferedImage

    我正在 java 小程序中制作游戏 并且正在尝试优化我的代码以减少闪烁 我已经实现了双缓冲 因此我尝试使用另一个 BufferedImage 来存储不改变的游戏背景元素的图片 这是我的代码的相关部分 public class QuizApp
  • Spring表单ModelAttribute字段验证避免400 Bad Request错误

    我有一个ArticleFormModel包含正常发送的数据html form由 Spring 使用注入 ModelAttribute注释 即 RequestMapping value edit method RequestMethod PO

随机推荐