【问题标题】:How to resolve from an Injeactable its caller class?如何从 Injeactable 中解决其调用者类?
【发布时间】:2017-02-04 06:00:12
【问题描述】:

假设我是一个注入类 B 的 A 类。在 B 类中,我需要隐式获取具有注入类 B 的类。所以在这种情况下,这将是 A 类。

有谁知道如何以稳健的方式接收这个?

也试过了,但这给了我 Logger 而不是它的调用者。

Something like

@Stateless
@Dependent
public class Logger {

@Inject
InjectionPoint ip;

@Asynchronous
public void doSomething(){
   ip.getMember().getDeclaringClass().getName()
 }
}

【问题讨论】:

    标签: java jakarta-ee dependency-injection cdi


    【解决方案1】:

    如果我们谈论的是 @Dependent 作用域 bean,那就是 a way documented in the CDI spec

    一般的想法是,CDI 允许您注入一个名为 InjectionPoint 的对象,并且您可以从中获取有关注入此 bean 的 bean 的信息。

    这是一个简短的 sn-p:

    @Dependent //if you don't declare any scope, it's @Dependent by default
    public class MyBean {
      @Inject
      InjectionPoint ip;
    
      public void doStuff() {
        // gives you the name of declaring class
        ip.getMember().getDeclaringClass().getName(); 
      }
    }
    

    或者,您可以在 bean 中使用构造函数注入来在 bean 创建期间处理此问题。它可能更接近您的目标:

    @Dependent //if you don't declare any scope, it's @Dependent by default
    public class MyAnotherBean {
      public MyAnotherBean(InjectionPoint ip) {
        // CDI will inject InjectionPoint automatically
        ip.getMember().getDeclaringClass().getName(); 
      }
    }
    

    再次注意,这仅适用于@Dependent!为什么?好吧,因为@Dependent 为每个注入点创建新实例并且不使用代理。因此,您还可以准确地知道您为谁创建此实例。其他范围,例如@RequestScoped@SessionScoped 等,确实使用代理,因此您只需在 CDI 中实例化一个对象,然后在请求注入时传递代理。

    【讨论】:

    • 谢谢,这似乎有效。这确实看起来像一个更优雅的解决方案!也感谢您的清晰解释!
    • @Bgvv1983 欢迎您。顺便说一句,我看到您将自己的答案标记为解决方案。我的回答有什么遗漏吗?只是问我是否可以/应该提供任何进一步的信息:)
    • Hmzz 似乎无法正常工作 ip.getMember().getDeclaringClass().getName();给出 MyBean.class。
    • 您没有提供任何代码片段,所以我不知道MyBean.class 是什么,您希望得到什么?另外,你的 bean 的作用域是什么?
    • 嗯,我明白了。实际上,您在那里有 EJB bean,而不仅仅是 CDI。我不确定一起工作。我会仔细检查并联系您。
    【解决方案2】:

    看来我找到了解决办法。

    创建了一个 HelperClass。其中包含一个 @AroundInvoke 方法。

    @AroundInvoke
    public Object injectMap(InvocationContext ic) throws Exception {
        StackTraceElement element = Thread.currentThread().getStackTrace()[CLASS_NAME_ELEMENT];
        return ic.proceed();
    }
    

    在A类中我注释了需要使用可注入类B的方法:

    @Interceptors(ContextHelper.class)
    

    这似乎符合我的要求。

    【讨论】:

    • 虽然这可能行得通,但它看起来很硬核。无论如何,我建议使用 CDI 拦截器(例如注释 @Interceptor@InterceptorBinding),而不是像这里那样使用 EJB 拦截器。虽然这可能有效,但 EJB 拦截器并不是 CDI 中的一等公民。
    猜你喜欢
    • 2021-07-07
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多