【问题标题】:Java EE CDI Instance | How to get real classJava EE CDI 实例 |如何获得真正的课程
【发布时间】:2020-11-27 16:10:24
【问题描述】:

我正在尝试访问通过 CDI 注入的实例的真实类。 我只得到一个类名的名称,它由接口名称、数字序列和字符串“$Proxy$_$$_Weld$EnterpriseProxy$”组成。

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestProvider {
    String value();
}

public interface TestConnector {

}

@TestProvider("TestConnector1")
@Stateless
public class Test1 implements TestConnector {

}

@Default
@TestProvider("TestConnector2")
@Stateless
public class Test12 implements TestConnector {

}

@Stateless
public class TestFactory {
    
    @Inject
    @Any
    private Instance<TestConnector> testConnectors;
    
    public TestConnector getConnector(String name) {
        ...
    }
    
    public Set<String> listAllTestConnectorNames(){
        try {
            Set<String> connectors = new HashSet<String>();
            
            this.testConnectors.forEach(con -> {
                System.out.println(con.getClass().getName());
                for(Annotation x : con.getClass().getAnnotations()) {
                    if(x instanceof TestProvider) {
                        String name = ((TestProvider) x).value();
                        System.out.println(name);
                        connectors.add(name);
                    }
                }
                this.testConnectors.destroy(con);
            });
            
            return connectors;
        } catch(Exception e) {
            ...
    }
}

函数 listAllTestConnectorNames 应该遍历所有确定的实例并将注释 TestProvider 的值作为列表返回。 我希望得到以下列表。

  • TestConnector1
  • TestConnector2

但我收到的实例类型为 de.test.con1.TestConnector $ 710153185 $ Proxy $ _ $$ _ Weld $ EnterpriseProxy $ 或 de.test.con2.TestConnector $ 219965632 $ 代理 $ _ $$ _ Weld $ EnterpriseProxy $

如何读出我正在寻找的值?

【问题讨论】:

  • 您的问题似乎是xy one。为什么需要这样的数据?是在运行时选择给定的实现吗? this 能解决你真正的问题吗?在更复杂的情况下,您可以使用 testConnectors.select 和适当的 AnnotationLiteral 来“动态地”选择您的本。这是你的具体目标吗?
  • 这背后有一个真正的问题。我需要获取 TestProvider 注释的相应值。对于stackoverflow,类、注释和接口仅称为“textXYZ”。在实际应用中,这些名称当然是合理的。
  • 我不是故意冒犯你的。我知道你有一个真正的问题。我的观点是,也许您解决问题的方法可以通过更倾向于架构的方式进行交换,而不是干预类层次结构,或者如@laid-nelson 的回答中所建议的那样,与给定的实现弱链接。无论如何,如果您遵循答案,您将在一段时间内安全(而 Weld 不会进行更改)。

标签: java cdi java-ee-7


【解决方案1】:

您的 TestConnector 实例正在被 Weld 代理,可能是因为它们位于 normal scope 中。这很好,符合预期。

因此,您的问题是:“给定一个(焊接定义的)代理类​​,我如何获得它所代理的‘真实’类的名称?”

没有一种方法可以保证工作,但这种方法适用于 CDI 的 Weld 实现:

Weld 的代理类在它们上设置了SYNTHETIC 标志,并且通常扩展它们所代理的类。我不认为这是有保证的,但许多版本和多年以来都是如此。

所以如果你这样做:

Class<?> c = proxyClass;
while (c.isSynthetic()) {
  c = c.getSuperclass();
}
// Now c is the "real" class
System.out.println(c.getName()); // shouldn't be a proxy class name anymore

……你应该很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    • 2017-01-09
    • 2011-10-15
    • 2015-07-29
    • 2013-05-06
    相关资源
    最近更新 更多