gpt4 book ai didi

java - cglib 代理类中缺少字段注释

转载 作者:行者123 更新时间:2023-12-04 11:00:29 24 4
gpt4 key购买 nike

@Service
public class TestService{

@DynamicReference
private ITestProvider testProvider;

public void run() {

}
}
DynamicReference dynamicRefrence = filed.getAnnotation(DynamicReference.class);
-->NOT NULL

在这种情况下,这段代码很好。但是当我添加 @Transactional在方法运行中,然后 @DynamicReference会输
@Service
public class TestService{

@DynamicReference
private ITestProvider testProvider;

@Transactional
public void run() {

}
}
DynamicReference dynamicRefrence = filed.getAnnotation(DynamicReference.class);
-->NULL

如何获取字段注释 @DynamicReference在 cglib 代理类中?

这是获取字段代码:
Object o = this.applicationContext.getBean(beanName);
Class<?> clazz = o.getClass();

for (Field filed : clazz.getDeclaredFields()) {
DynamicReference dynamicRefrence = filed.getAnnotation(DynamicReference.class);
}

最佳答案

来自 Class.getDeclaredFields() :

Returns an array of Field objects reflecting all the fieldsdeclared by the class or interface represented by this Class object. This includes public, protected, default(package) access, and private fields, but excludes inherited fields.



在您的情况下,一旦您拥有来自 cglib 的基于子类的代理,该字段将仅存在于父类(super class)中。根据您的用例,您可能希望收集具有自定义注释的继承链中的所有字段。

示例代码:
    Collection<Field> fieldsWithAnnotation = new ArrayList<>();

Class<?> clazz = // your class

while(clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
DynamicReference dynamicRefrence = field.getAnnotation(DynamicReference.class);
if(dynamicRefrence != null)
fieldsWithAnnotation.add(field);
}
clazz = clazz.getSuperclass();
}

编辑:这种方法可以找到带注释的字段。然而,做 field.set(proxyInstance, value)实际上会在代理中设置字段。这对您没有帮助,因为即使代理子类,它仍然使用委托(delegate)将方法调用转发到实际类的包装实例。由于您的目标显然是在此包装实例中设置字段,因此我建议您不要使用自定义字段注入(inject),而是使用 setter 注入(inject)。您的代码大致如下所示(未经测试):
// in TestService
private ITestProvider testProvider;

@DynamicReference
public void setTestProvider(ITestProvider testProvider) { ... }

// Getting the method
while(clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
DynamicReference dynamicRefrence = method.getAnnotation(DynamicReference.class);
if(dynamicRefrence != null)
methodsWithAnnotation.add(method);
}
clazz = clazz.getSuperclass();
}

// invoking it
method.invoke(proxyInstance, dependencyInstanceYouWantToSet);

代理应该将方法调用委托(delegate)给您的包装实例。也许您甚至想让该方法受到保护。

另一种方法是获取代理的回调字段并在该实例上设置该字段,但上面的方法似乎更干净(有人可能会说魔法字段注入(inject)是邪恶的,您应该始终使用 setter/constructor 注入(inject)来实现干净的 oop方法)。

编辑 2:也许您还可以重新考虑是否要真正重新发明 DI 框架并利用底层现有的 DI 框架功能。想到使用 @Qualifier 或一些自定义注入(inject)解析器。参见例如 this tutorial

关于java - cglib 代理类中缺少字段注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58832289/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com