在运行时

时间:2017-10-31 20:33:40

标签: java java-ee dependency-injection cdi

假设我定义了以下服务接口(以及实现):

interface Service1 { /* Methods omitted for brevity */ }
interface Service2 { /* Methods omitted for brevity */ }

我也有这个无法修改的界面(它不在我的手中):

interface YouAreNotAllowedToModifyMe {
  Object createSomething();
}

进一步假设我有一个实现YouAreNotAllowedToModifyMe接口的类,并接受这些服务的实现以及当前的HttpServletRequest。请注意,请求是实现细节,而不是接口的一部分。

class Demo implements YouAreNotAllowedToModifyMe {

  private final HttpServletRequest request;
  private final Service1 service1;
  private final Service2 service2;

  @Inject
  public Demo(HttpServletRequest request, Service1 service1, Service2 service2) {
    this.request = request;
    this.service1 = service1;
    this.service2 = service2;
  }

  public Object createSomething() {
    // Use the request, service1, and service2 in order to create the object.
  }
}

Demo直到运行时才能实例化,因为它需要当前的HttpServletRequest,但是我希望CDI注入能够注入其他参数。我怎么能这样做?

基本上,我希望这是可能的(它不是):

class Foo {

  @Inject
  private final Instance<Demo> demoInstance;

  public void doSomething(HttpServletRequest request) {

    // This is pretend. This won't really work, though I wish it would.
    // Essentially, I pass in the request and CDI takes care of everything else.
    Demo demo = demoInstance.get(request);
  }
}

1 个答案:

答案 0 :(得分:1)

不能使用注入了一半参数的构造函数和一半手工提供的构造函数。但是你有其他选择:

  • HttpServletRequest创建一个制作人。更好的是,使用Delta Spike。那么你实际上可以注入 HttpServletRequest
  • Demo修改为YouAreNotAllowedToModifyMe的实例 factory ,而不是实现它:

    @ApplicationScoped //probably-but not necessarily???
    public class Demo {
        @Inject
        private final Service1 service1;
        @Inject
        private final Service2 service2;
    
        public YouAreNotAllowedToModifyMe makeYouAreNotAllowedToModifyMe(HttpServletRequest request) {
            return new YouAreNotAllowedToModifyMeImpl(request);
        }
    
        private class YouAreNotAllowedToModifyMeImpl implements YouAreNotAllowedToModifyMe {
            YouAreNotAllowedToModifyMeImpl(HttpServletRequest request) {
                // do what you must...
            }
    
            // implement it!
            // remember, you can actually use service1 &
            // service 2 from the enclosing instance
        }
    }