java - 构造函数注入在 Servlet + WELD + Tomcat 中不起作用
问题描述
我在 CDI 中遇到构造函数注入问题。字段或属性注入工作正常。字段注入实例的构造函数注入也可以正常工作。唯一不工作的 - Servlet 类中的构造函数注入。
配置:WEB-INF 中的空 beans.xml,context.xml 中定义的 BeanManager。
环境:Tomcat 9.0.24,CDI,WELD 实现。
示例代码:
@WebServlet(urlPatterns = "/servlet/*")
public class SimpleServlet extends HttpServlet implements Serializable {
// @Inject
private TestService testService;
@Inject
public SimpleServlet(TestService testService) {
this.testService = testService;
}
// Without this constructor (even protected) I have Exception java.lang.NoSuchMethodException: SimpleServlet.<init>()
public SimpleServlet() {
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// This prints null when using constructor injection
// Prints instance hashcode when using field injection
resp.getWriter().write(testService + "");
}
@PostConstruct
public void onPostConstruct() {
System.out.println("This is invoked everytime");
// Null when constructor injection
System.out.println(testService);
}
}
POM.xml
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-shaded</artifactId>
<version>3.1.2.Final</version>
</dependency>
</dependencies>
Servlet 内 ConstructorInjection 的 StackTrace:
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:151)
at org.jboss.weld.environment.tomcat.ForwardingInstanceManager.newInstance(ForwardingInstanceManager.java:26)
at org.jboss.weld.environment.tomcat.WeldForwardingInstanceManager.newInstance(WeldForwardingInstanceManager.java:71)
以及其他类中的 ConstructorInjections:
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:119)
at org.jboss.weld.injection.ConstructorInjectionPoint.invokeAroundConstructCallbacks(ConstructorInjectionPoint.java:92)
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:78)
所以 Servlet 内部的 WELD 使用 ForwardingIntranceManager,但在其他类 ConstructorInjectionPoint 内部。WELD里面的错误可能吗?
解决方案
您是否已经尝试过降级 CDI 版本?尝试在 pom.xml 中更改这些依赖项。
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.2.9.Final</version>
</dependency>
推荐阅读
- android - AOSP 构建系统中用用户标记的模块是什么
- environment-variables - 检测 Tcl 中的环境变量变化
- clickhouse - 位图sql的写法太繁琐,如何简化
- security - Google 控制台 Firebase 机器人测试中的 WebView 内容安全策略异常
- react-native - React Native - 带有 react-navigation 和 typescript 的 I18Next
- activemq-artemis - 在 ActiveMQ Artemis 代理上发送请求时生产者超时
- c++ - 为 GCC 构建 64 位 GNU GMP
- opsgenie - 当警报计数超过 Opsgenie 中的某个值时创建事件
- if-statement - Github Actions IF 表达式语法的问题
- apache-spark - Spark on Yarn - Prometheus 发现