首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >@ ServletContextListener中的自动连线

@ ServletContextListener中的自动连线
EN

Stack Overflow用户
提问于 2013-07-15 21:58:36
回答 5查看 17K关注 0票数 8

我有一个InitApp班级

代码语言:javascript
复制
@Component
public class InitApp implements ServletContextListener {

@Autowired
ConfigrationService weatherConfService;

/** Creates a new instance of InitApp */
public InitApp() {
   }

public void contextInitialized(ServletContextEvent servletContextEvent) {
    System.out.println(weatherConfService);
   }
public void contextDestroyed(ServletContextEvent servletContextEvent) {
   }
}

和web.xml中的listener:

代码语言:javascript
复制
    <listener>
        <listener-class>com.web.Utils.InitApp</listener-class>
    </listener>

    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

confService打印--> null有什么问题?

EN

回答 5

Stack Overflow用户

发布于 2015-06-04 22:28:21

当我遇到同样的问题时,我想到了几个想法。

第一个方法是使用Spring utils从侦听器内的Spring上下文中检索bean:

例如:

代码语言:javascript
复制
@WebListener
public class CacheInitializationListener implements ServletContextListener {

    /**
     * Initialize the Cache Manager once the application has started
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        CacheManager cacheManager = WebApplicationContextUtils.getRequiredWebApplicationContext(
                sce.getServletContext()).getBean(CacheManager.class);
        try {
            cacheManager.init();
        } catch (Exception e) {
            // rethrow as a runtime exception
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub

    }
}

如果您只有一个或两个bean,则可以很好地工作。否则,它会变得单调乏味。另一种选择是显式调用Spring的Autowire实用程序:

代码语言:javascript
复制
@WebListener
public class CacheInitializationListener implements ServletContextListener {

    @Autowired
    private CacheManager cacheManager;

    /**
     * Initialize the Cache once the application has started
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        try {
            cacheManager.init();
        } catch (Exception e) {
            // rethrow as a runtime exception
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub

    }
}

在这两个解决方案中需要注意的是,必须先加载Spring上下文,然后才能使用它们。鉴于无法使用@WebListener定义侦听器顺序,请确保在web.xml中定义Spring ContextLoaderListener,以强制首先加载它(在web描述符中定义的侦听器在通过注释定义的侦听器之前加载)。

票数 10
EN

Stack Overflow用户

发布于 2013-07-15 22:01:22

通过声明

代码语言:javascript
复制
<listener>
  <listener-class>com.web.Utils.InitApp</listener-class>
</listener>

在web.xml中,您告诉容器初始化并注册InitApp的一个实例。因此,该对象不是由Spring管理的,您不能将任何内容@Autowired到其中。

如果您的应用程序上下文设置为对com.web.Utils包进行组件扫描,那么您将拥有一个没有注册为容器侦听器的InitApp bean。因此,即使您的另一个bean将是@Autowired,servlet容器也不会命中它。

这就是权衡。

如果对Servlet3.0的ServletContainerInitializerWebApplicationInitializer使用编程配置,则可以解决此问题。您不会使用@Autowired,您只需要使用setter/getter来设置实例。

下面是一个例子

代码语言:javascript
复制
class SpringExample implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        WebApplicationContext context = ...;

        SomeBean someBean = context.getBean(SomeBean.class);
        CustomListener listener = new CustomListener();
        listener.setSomeBean(someBean);

        // register the listener instance
        servletContext.addListener(listener);

        // then register DispatcherServlet and ContextLoaderListener, as appropriate
        ...
    }
}

class CustomListener implements ServletContextListener {
    private SomeBean someBean;

    public SomeBean getSomeBean() {
        return someBean;
    }

    public void setSomeBean(SomeBean someBean) {
        this.someBean = someBean;
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
       // do something with someBean
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

请注意,Spring有一些非常复杂的WebApplicationInitializer自定义实现。你真的不需要自己直接实现它。这个想法保持不变,只是在继承层次中更深一层。

票数 6
EN

Stack Overflow用户

发布于 2018-04-05 17:19:42

代码语言:javascript
复制
@WebListener
public class StartupListener implements ServletContextListener {

    @Autowired
    private MyRepository repository;

    @Override
    public void contextDestroyed(ServletContextEvent event) {
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        AutowireCapableBeanFactory autowireCapableBeanFactory = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext()).getAutowireCapableBeanFactory();
        autowireCapableBeanFactory.autowireBean(this);

        repository.doSomething();
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17656046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档