【问题标题】:How to get ApplicationScoped producer in Java SE via weld?如何通过焊接在 Java SE 中获得 ApplicationScoped 生产者?
【发布时间】:2016-02-08 18:27:55
【问题描述】:

我正在尝试使用 Weld 在我的 Java SE 程序中实现依赖注入,但我在使用应用程序范围的生产者时遇到了问题。这是我的问题的 PoC,代码最少。 MyBean 类:

public class MyBean implements Serializable{
  private int value;

  public MyBean(int value) {
    this.value = value;
  }

  public int getValue() {
    return value;
  }

  public void setValue(int value) {
    this.value = value;
  }
}

注入点:

@Path("api")
public class MyResource implements Serializable {
  @Inject
  private MyBean bean;

  @GET
  @Path("bean")
  @Produces(MediaType.APPLICATION_JSON)
  public Response getBean() {
    return Response.ok(bean).build();
  }
}

我希望它的生产实例为@ApplicationScoped 的生产者是:

public class BeanProducer {

  @Produces
  @ApplicationScoped
  public MyBean beanProducer(){
    System.out.println("producing");
    return new MyBean(42);
  }
}

所有这些都绑定在一个主类中:

public class Main {
  public void main(@Observes ContainerInitialized event) {
    try {
      URI baseUri = UriBuilder.fromUri("http://localhost").port(1234).build();
      ResourceConfig config = new ResourceConfig(MyResource.class)
          .register(JacksonFeature.class);
      SimpleServer server = SimpleContainerFactory.create(baseUri, config);
      System.in.read();
      server.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

当我尝试运行它时,我得到以下异常:

线程“main”中的异常 org.jboss.weld.exceptions.DeploymentException:WELD-001410: 注入点 [BackedAnnotatedField] @Inject @ApplicationScoped 私有 MyResource.bean 具有不可代理的依赖项 org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:392) 在 org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:293) 在 org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134) 在 org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:167) 在 org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:530) 在 org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:68) 在 org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:66) 在 org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:60) 在 org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:53) 在 java.util.concurrent.FutureTask.run(FutureTask.java:266) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 在 java.lang.Thread.run(Thread.java:745) 引起: org.jboss.weld.exceptions.UnproxyableResolutionException:WELD-001435: 普通范围的 bean 类 MyBean 是不可代理的,因为它没有 无参数构造函数 - 带有限定符的生产者方法 [MyBean] [@Any @Default] 声明为 [[BackedAnnotatedMethod] @Produces @ApplicationScoped public BeanProducer.beanProducer()]。在 org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:214) 在 org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:178) 在 org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:390) ... 12 更多

如果我为生产者定义范围,它将不起作用。 如果我将注入点范围设置为@ApplicationScoped 并且生产者没有任何范围,它可以按我的意愿工作,这意味着我将在我的应用程序的整个生命周期中拥有一个 bean 实例。

但是将注入点的作用域设置为@ApplicationScoped与默认作用域相同,即。每个请求都有一个新实例。

这一切背后的原因是什么?

【问题讨论】:

    标签: java scope cdi weld


    【解决方案1】:

    这是因为@ApplicationScoped 是一个普通范围,它需要是可代理的。要成为可代理,您需要一个无参数构造函数。

    澄清你的观点之一

    it works as I want, means I will have a single instance of the bean in the entire lifecycle of my app.
    

    这不准确。注入点不定义范围,生产者定义。在 Java 中没有类型安全的方法可以做到这一点,因为您可以拥有一个生产者字段。

    【讨论】:

    • 添加默认构造函数会使依赖关系变得模糊,因为 Weld 不知道是使用生产者还是直接注入 bean 本身。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 2016-03-17
    • 2016-02-03
    相关资源
    最近更新 更多