这是我第一次尝试 CDI。我有一个 Eclipse Kepler 环境,其中有一个部署在内部 Glassfish 4.0 运行时上的 Maven Web 项目。
它有一个 servlet 和一个 JAX-RS 资源 POJO,两者都可以正常工作。接下来,我在与 servlet 和 JAX-RS POJO 相同的包中创建了一个类:
package com.example.test;
import java.util.logging.Logger;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
@ApplicationScoped
public class Bean {
@Produces @ApplicationScoped
public static Bean produce () {
return new Bean();
}
public Bean () {
Logger.getGlobal().info("Bean()");
}
}
Run Code Online (Sandbox Code Playgroud)
我修改了POJO:
package com.example.test;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Resource(name = "foo", type = Rest.class)
@Path("/rest")
public class Rest {
@Inject Bean …
Run Code Online (Sandbox Code Playgroud) 我的拦截器没有在应该启动的时候启动,即使它已在 bean 中注册并且文件没有提供任何警告。我缺少什么?
编辑1:我希望能够在每次Genres.java
调用和离开函数时进行记录,但使用此配置我根本没有得到任何输出。
编辑 2:按照 Svetlin 的建议应用断点后,我可以确认代码永远不会到达拦截器或生产者。
beans.xml
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
<interceptors>
<class>no.krystah.log.LoggingInterceptor</class>
</interceptors>
</beans>
Run Code Online (Sandbox Code Playgroud)
日志拦截器.java
package no.krystah.log;
import javax.inject.Inject;
import javax.interceptor.AroundConstruct;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import org.slf4j.Logger;
@Log @Interceptor
public class LoggingInterceptor {
@Inject
Logger logger;
@AroundConstruct
private void init(InvocationContext ic) throws Exception {
logger.info("Entering constructor");
try {
ic.proceed();
} finally {
logger.info("Exiting constructor");
}
}
@AroundInvoke
public Object logMethod(InvocationContext ic) throws Exception {
logger.info(ic.getTarget().toString()+" - "+ ic.getMethod().getName()); …
Run Code Online (Sandbox Code Playgroud) 我有一个在 JBoss/Wildfly 上运行的应用程序。我使用 CDI 事件在模块之间进行通信。我希望能够使用事件作为插入自定义的一种方式,基本上动态加载一个额外的观察者,该观察者也将接收 CDI 事件。
这是我用来从 EJB 中动态加载类的片段:
File file = new File("D:\\workspace\\integrator\\target\\classes\\");
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
ClassLoader cl = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
Class cls = cl.loadClass("demo.DemoObserver");
observerInstance=cls.newInstance();
Run Code Online (Sandbox Code Playgroud)
加载的类非常简单,只是一个普通的 CDI 事件观察器,注释为 @Dependent 以“看到”为一个 bean。我的 beans.xml 被配置为自动发现 bean。
@Dependent
public class DemoObserver {
private boolean observed=false;
public DemoObserver() {
observed=false;
}
@PermitAll
public void stateChanged(@Observes EquipmentE10StateChanged event) {
observed=true;
System.out.println("Demo observer received event E10 state changed: " + event.toString());
}
}
Run Code Online (Sandbox Code Playgroud)
该类已加载并实例化(我可以看到来自其构造函数的日志),但它从不接收事件。
有什么我可以做的事情吗?
将java.util.Random注入Bean时,部署失败:
CDI部署失败:WELD-001408:类型为Random的不满意依赖项,注入点为@Default限定符[BackedAnnotatedField] @Inject myPackage.MyBean.random
问题:为什么不能注入java.util.Random类的实例?
我创建了一个具有类似属性的类A(比如具有默认可见性的最终方法),它可以毫无问题地注入.这是代码:
@Named
@SessionScoped
public class MyBean implements Serializable {
@Inject private java.util.Random random; // (R)
@Inject private A a;
...
}
public class A implements Serializable {
int n;
public A() { System.out.println("A"); }
public A(int n) { this.n = n; }
final int nextInt(int bound) { return bound -n; }
}
Run Code Online (Sandbox Code Playgroud)
如果将行(R)注释掉,那么一切都会部署并运行正常.