Java @ServletContextListener中的自动连线
我有一个初始化应用程序Java @ServletContextListener中的自动连线,java,spring,spring-mvc,Java,Spring,Spring Mvc,我有一个初始化应用程序 @Component public class InitApp implements ServletContextListener { @Autowired ConfigrationService weatherConfService; /** Creates a new instance of InitApp */ public InitApp() { } public void contextInitialized(ServletContextEvent
@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>
<listener-class>com.web.Utils.InitApp</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
com.web.Utils.InitApp
org.springframework.web.context.ContextLoaderListener
服务打印-->为空
什么问题?通过声明
<listener>
<listener-class>com.web.Utils.InitApp</listener-class>
</listener>
请注意,Spring有一些非常复杂的
WebApplicationInitializer
自定义实现。你真的不需要自己直接实现它。这个想法保持不变,只是在继承层次结构的更深层。正如其他人所说,这个侦听器通过web servlet(tomcat)上下文(而不是Spring容器)进行观察,并收到servlet启动/关闭的通知
因为它是由Spring容器外部的servlet创建的,所以它不是由Spring管理的,因此@Autowire成员是不可能的
如果将bean设置为托管@组件,那么Spring将创建实例,侦听器将不会向外部servlet注册
你不能两全其美
一种解决方案是删除Spring注释并从Spring应用程序上下文中手动检索您的成员,并以此方式设置您的成员
即
当我遇到同样的问题时,我想到了一些想法 第一个是使用Spring UTIL从侦听器中的Spring上下文检索bean: 例: 如果你只有一两颗豆子,这个方法就可以了。否则它会变得乏味。另一个选项是显式调用Spring的Autowire实用程序:
@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
中定义了SpringContextLoaderListener
,以强制首先加载它(在web描述符中定义的侦听器在通过注释定义的侦听器之前加载).您应该在xml Spring配置中定义ConfigurationService
,正如Nambari所指出的,或者,您应该将组件扫描
放在包含配置服务
的软件包上,并使用@component
或@service
对服务进行注释。您可以提供一个解决方法的示例吗?我很难理解@Configuration
bean如何将一些东西注入到由容器管理的bean中。@Config
bean如何获得容器bean的引用?@EricB。使用ServletContainerInitializer
和WebApplicationInitializer
您自己正在初始化和注册ServletContextListener
。由于您还可以访问SpringWebApplicationContext
,因此可以从中检索bean并将其交给侦听器。@EricB。(如果你想要一个完整的例子,你必须稍后再给我。)当然-我可以使用类似webapplicationcontextils.getRequiredWebApplicationContext
的东西来检索应用程序上下文,然后从中获取bean,但我不确定这是否是你的意思。我从你的帖子中了解到,这可以通过Spring配置类完成,并将Spring bean推送到监听器中(而不是让监听器从Spring上下文中提取bean),我很想看看如何在Spring中操纵listener bean。
public class InitApp implements ServletContextListener {
private ConfigrationService weatherConfService;
private static ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:web-context.xml");
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
weatherConfService = applicationContext.getBean(ConfigrationService.class);
System.out.println(weatherConfService);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
@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
}
}
@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
}
}
@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();
}
}