- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试为带有字节伙伴的字段创建一个“自定义”setter 方法。Buddy 自己的机制允许非常容易地实现标准的 setter/getter 方法,但是,我正在寻找一种优雅的方式来使用一些额外的逻辑来扩展 setter。
为简化示例,假设我们有一个类 A,它有一个方法 setChanged(String)。目标是做一个A的子类,添加一个字段对应的访问方法。问题是,我想从每个添加的 setter 方法中调用 setChanged("fieldName")。
public void setName(String name)
{
setChanged("name");
this.name = name;
}
对于“普通”setter 方法,byte byddy 实现将是:
new ByteBuddy()
.subclass(A.class)
.name("B")
.defineField("name", Integer.TYPE, Visibility.PUBLIC)
// args is a ArrayList<Class<?>>
.defineMethod(getSetterName(name), Void.TYPE, args, Visibility.PUBLIC)
.intercept( FieldAccessor.ofField(name) )
我想要的字节码是这样的:
L0
ALOAD 0 // Loads the this reference onto the operand stack
ILOAD 1 // Loads the integer value of the local variable 1 (first method arg)
PUTFIELD package/B.name : I // stores the value to the field
L1
ALOAD 0
LDC "name"
INVOKEVIRTUAL package/A.setChanged (Ljava/lang/String;)V
RETURN
我的问题是:有没有办法在这种情况下重用 FieldAccessor?
最佳答案
从今天开始,您需要定义一个自定义的 Instrumentation
来完成这样的自定义工作。正如评论中所指出的,您随后可以使用 Instrumentation.Compound
将新行为添加到例如 FieldAccessor.ofBeanProperty()
之前,从而重用字段访问器代码。
为了添加自定义代码,字节好友了解不同的抽象级别:
Instrumentation
:定义方法的实现方式。仪器能够定义实现方法所需的附加字段、方法或静态初始化程序 block 。此外,它确定是否要为类型定义方法。ByteCodeAppender
由 Instrumentation
发出,并确定定义的方法是否是抽象的,如果方法已实现,则确定方法的字节码。StackManipulation
是一个字节码指令,对操作数栈的大小有一定的影响。堆栈操作用于实现非抽象方法。为了在字节码中调用方法,您需要将所有参数(包括this
)加载到堆栈上,并在放置所有这些参数后调用该方法。这可以按如下方式完成:
MethodVariableAccess.REFERENCE.loadFromIndex(0)
将 this
引用加载到堆栈上。ByteCodeAppender
的方法名称派生。使用 TextConstant
,然后可以将名称放在堆栈上。MethodInvocation
调用方法,其中 setChanged
方法可以从创建的检测类型的中提取>TypeDescription
作为参数提供给 Instrumentation
。当然,这不是很漂亮,Byte Buddy 的愿望是向用户隐藏这个字节代码级别的 API,并用 DSL 或纯 Java 表达任何内容。因此,您可能会很高兴听到我目前正在使用 Byte Buddy 0.4 版,它具有一些您可以用于此目的的功能。对于您的示例,您可以使用 Byte Buddy 瑞士军刀的扩展形式 MethodDelegation
来实现自定义 setter 。方法委托(delegate)允许您通过使用注释委托(delegate)对任何 Java 方法的调用来实现方法。
假设您的 bean 实现了一个类型:
interface Changeable {
void setChanged(String field);
}
您可以使用以下方法拦截方法调用:
class Interceptor {
static void intercept(@This Changeable thiz, @Origin Method method) {
thiz.setChanged(method.getName());
}
}
使用方法委托(delegate),字节好友将始终在调用方法时调用拦截器。向拦截器方法传递描述特定拦截上下文的参数。上面,传递了this
引用和被拦截的方法。
当然我们还缺少字段的实际设置。但是,使用 Byte Buddy 0.4,您现在可以创建一个新的 Instrumentation
,如下所示:
MethodDelegation.to(Interceptor.class).andThen(FieldAccessor.ofBeanProperty())
有了这个委托(delegate),Byte Buddy 首先调用 intercepor(然后丢弃任何潜在的返回值),最后应用作为参数传递给 andThen
方法的 Instrumentation
.
关于Java 字节码 : Customized setter/getter with byte buddy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26627981/
如果您有一个具有一些普通 get/set 属性的类,是否有任何理由在类方法中使用 getter,或者您应该只使用私有(private)成员变量?我认为关于setter(验证逻辑?)可能会有更多争论,但
我是 Android 编程的新手(~ 2 个月)有必要为几十个不同的变量设置 getter 吗? 例如—— //Yes I realise that this isn't 'dozens' publi
我是VUEX新手,在学习VUEX的同时搭建了一个测试应用。我已将我的 VUEX 存储拆分为多个模块,每个模块都有自己的 getter.js 文件。 Getters、 Action 、突变被导入到每个模
我有一项服务正在加载我想在多个组件之间共享的基本系统信息。 如果我在 getter 中创建一个 getter 方法 this 如果我不在服务中使用双箭头,则 getter 中的 this 成为组件的
tl;博士 如何从参数化的 getter 访问其他 getter? 通常可以使用this.myGetter ;但是参数化的 getter 被实现为箭头函数,其中 this未定义。 在 Pinia 中处
我第一次尝试做一些 OOP,这不是简单的练习,而是用 java 编写一个程序来存储有关人员的信息(如通讯录)。下面是我正在开发的名为 Person 的类的片段。 Person 将在将来的某个时间被其他
我在某处看到类似下面的内容,想知道它是什么意思。我知道他们是getter和setter,但是想知道为什么字符串Type是这样定义的。谢谢你帮助我。 public string Type { get;
Public class Example { private int number; public Example(int number){ this.number =
getter 应该只返回对象吗: public MyObject getMyObject() { return myObject; } 或者它应该复制它返回的对象并返回该副本? public
我目前正在处理大量数据输入,包括很多值,我希望在 getter 中接收这些值以供以后使用。 在编写了一些方法之后,我想知道仅使用一个 get 方法是否是一个更好的主意,并使用一个包含所有可能值的枚举类
我正在使用新的 Class Public Field Declarations可用 Chrome 72我遇到了这种真正奇怪的行为: class Extended { property = 5; }
我有一个这样的表达式 setter/getter : var expression = () => SomeInstance.Nr; 它被传递到一个方法中: public void AddExpres
我的一个类(class)中有以下 getter: get password(){ if(this._public) return null; var text = ""
我已经设法测试了与其他代码隔离的 Vuex getter。当 getter 依赖于其他 getter 时,我现在面临一些问题,请参见以下示例: getters.js export const gett
有时我的任务是查找 getter 返回的值中的某些嵌套 getter 是否具有某些属性。经典的 C++ 会是这样的: for (const auto& label: labels) for (co
我有一个像这样的基类“Parent”: using System; using System.Collections.Generic; using System.Text; namespace Con
我一直在努力了解 getter 和 setter,但没有深入了解。我读过 JavaScript Getters and Setters和 Defining Getters and Setters只是没
考虑一个简单的 Vue 博客: 我使用 Vuex 作为我的数据存储,我需要设置两个 getters :一个 getPost getter,用于通过 ID 检索 post,以及一个 listFeatur
我有一个 VueX 商店,有两个模块,user.js 和merchant.js,顶层是index.js。 user.js 中的 getter 是: 重构 const getters = { s
我正在尝试向 jsp 添加一个复选框以在进入站点之前接受条款和条件。尽管我有一个 getter 方法并且没有看到任何拼写错误,但我一直收到关于没有 getter 方法的相同错误。我不明白我错过了什么。
我是一名优秀的程序员,十分优秀!