cglib代理类中缺少字段注释

@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

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

这是获取域代码:

Object o = this.applicationContext.getBean(beanName);
Class<?> clazz = o.getclass();

for (Field filed : clazz.getDeclaredFields()) {
    Dynamicreference dynamicrefrence = filed.getannotation(Dynamicreference.class);
}
qq9931 回答:cglib代理类中缺少字段注释

来自Class.getDeclaredFields()

  

返回一个Field对象数组,该对象反映由该Class对象表示的类或接口声明的所有字段。这包括公共,受保护的,默认(程序包)访问和私有字段,但不包括继承的字段。

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

示例代码:

    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)实际上将在代理中设置该字段。这对您没有帮助,因为即使代理子类仍然使用 delegation 将方法调用转发到实际类的包装实例。由于您的目标显然是在此包装好的实例中设置字段,因此建议您不要使用自定义的字段注入,而应使用setter注入。您的代码大致如下所示(未试用):

// 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);

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

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

编辑2:如果您想重新发明DI框架并利用现有的现有DI框架功能,也许您也可以重新考虑。想到使用@Qualifier或某些自定义注入解析器。参见例如this tutorial

本文链接:https://www.f2er.com/3112067.html

大家都在问