如何通过焊接在Java SE中获得ApplicationScoped生产者?

时间:2016-02-08 18:27:55

标签: java scope cdi 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:The   注入点[BackedAnnotatedField] @Inject @ApplicationScoped   private 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)at   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不可代理,因为它没有   no-args构造函数 - 带限定符的生成器方法[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与默认范围相同,即。每个请求的新实例。

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

1 个答案:

答案 0 :(得分:1)

这是因为@ApplicationScoped是正常范围,它需要是可代理的。要成为可代理的,你需要一个no-args构造函数。

澄清你的一点

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

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