简体   繁体   English

spring 依赖注入在用 @WebListener 注释的类中不起作用

[英]spring dependency injection is not working in a class annotated with @WebListener

I tried constructor based Dependency injection in TestAppListener class which implements ServletContextListener.我在实现 ServletContextListener 的 TestAppListener 类中尝试了基于构造函数的依赖注入。 I got this error Exception sending context initialized event to listener instance of class [com.example.listener.TestAppListener] .我收到此错误异常发送上下文初始化事件到类 [com.example.listener.TestAppListener] 的侦听器实例

I searched stack overflow but I couldn't find any solution for this scenario.我搜索了堆栈溢出,但找不到针对这种情况的任何解决方案。 Please any one help me in sort out this.请任何人帮我解决这个问题。 I placed Implementation classes in META-INF.services folder also.我也在 META-INF.services 文件夹中放置了实现类。 My understanding is there is some problem in constructor dependency injection but this way of DI is need for my situation, because in real time I want to create datasource connection inside startup method.我的理解是构造函数依赖注入存在一些问题,但是我的情况需要这种 DI 方式,因为我想实时在启动方法中创建数据源连接。

Find all my classes below which i'm using,在下面找到我正在使用的所有课程,

@WebListener
public class TestAppListener implements ServletContextListener {

private static TestDao dao;

public TestAppListener(TestDao dao){
    this.dao = dao;
}
public TestAppListener(){}

@Override
public void contextInitialized(ServletContextEvent sce) {
    dao = ServiceLoader.load(TestDao.class).iterator().next();
    dao.startUp();
    System.out.println("Context initialized method called");
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
    System.out.println("Context destroyed method called");
    dao.shutDown();
}

} }

public interface TestDao {

void startUp();

void shutDown(); 

} }

public class TestDaoImpl implements TestDao {
@Override
public void startUp() {
    System.out.println("Database is initialized");
}

@Override
public void shutDown() {
    System.out.println("Database is initialized");
}

} }

@Configuration
public class SpringConfig {

public SpringConfig() {
}

@Bean
public ServletListenerRegistrationBean<ServletContextListener> listenerRegistrationBean() {
    ServletListenerRegistrationBean<ServletContextListener> bean = new ServletListenerRegistrationBean<>();
    bean.setListener(new TestAppListener());
    return bean;
}

} }

Change private static TestDao dao to private final TestDao dao .private static TestDao dao更改为private final TestDao dao Spring doesn't allow statics to be used as targets for injection. Spring 不允许将静态用作注入目标。 Also, your TestDaoImpl class needs to be a component or a bean defined in a Spring configuration file.此外,您的TestDaoImpl类需要是 Spring 配置文件中定义的组件或 bean。

The Servlet @WebListener s are handled by Servlet containers(tomcat/Jetty) when the container is starting.当容器启动时,Servlet @WebListener由 Servlet 容器(tomcat/Jetty)处理。 So they know nothing about Spring.所以他们对Spring一无所知。

For more details, see discussion in this issue .有关更多详细信息,请参阅本期讨论

A workaround solution is replace the @WebListener with Spring's @Component , thus you can inject Spring beans(declare your Dao as spring beans) into the listeners directly.一种解决方法是将@WebListener替换为 Spring 的@Component ,因此您可以将 Spring bean(将您的 Dao 声明为 spring bean)直接注入侦听器。

BTW, you have to add @ServletComponentScan on your Spring Boot application class to activate it.顺便说一句,您必须在 Spring Boot 应用程序类上添加@ServletComponentScan才能激活它。

I created an example project to demo @WebServlet , @WebFilter and @WebListener .我创建了一个示例项目来演示@WebServlet@WebFilter@WebListener

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM