对于常规Servlet,我想你可以声明一个context listener,但对于Spring MVC,Spring会让这更容易吗?
此外,如果我定义了一个上下文侦听器,然后需要访问我的servlet.xml
或applicationContext.xml
中定义的bean,我将如何访问它们?
答案 0 :(得分:92)
Spring has some standard events which you can handle.
为此,您必须创建并注册实现ApplicationListener
接口的bean,如下所示:
package test.pack.age;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
public class ApplicationListenerBean implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
ApplicationContext applicationContext = ((ContextRefreshedEvent) event).getApplicationContext();
// now you can do applicationContext.getBean(...)
// ...
}
}
}
然后,您可以在servlet.xml
或applicationContext.xml
文件中注册此bean:
<bean id="eventListenerBean" class="test.pack.age.ApplicationListenerBean" />
并且Spring将在初始化应用程序上下文时通知它。
在Spring 3中(如果您使用的是此版本),ApplicationListener
class is generic并且您可以声明您感兴趣的事件类型,并相应地过滤事件。您可以像这样简化bean代码:
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
// now you can do applicationContext.getBean(...)
// ...
}
}
答案 1 :(得分:80)
从Spring 4.2开始,您可以使用@EventListener
(documentation)
@Component
class MyClassWithEventListeners {
@EventListener({ContextRefreshedEvent.class})
void contextRefreshedEvent() {
System.out.println("a context refreshed event happened");
}
}
答案 2 :(得分:6)
创建注释
@Retention(RetentionPolicy.RUNTIME)
public @interface AfterSpringLoadComplete {
}
创建课程
public class PostProxyInvokerContextListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
ConfigurableListableBeanFactory factory;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext context = event.getApplicationContext();
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
try {
BeanDefinition definition = factory.getBeanDefinition(name);
String originalClassName = definition.getBeanClassName();
Class<?> originalClass = Class.forName(originalClassName);
Method[] methods = originalClass.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(AfterSpringLoadComplete.class)){
Object bean = context.getBean(name);
Method currentMethod = bean.getClass().getMethod(method.getName(), method.getParameterTypes());
currentMethod.invoke(bean);
}
}
} catch (Exception ignored) {
}
}
}
}
通过@Component注释或xml
注册此类<bean class="ua.adeptius.PostProxyInvokerContextListener"/>
并使用注释来处理在上下文初始化后要运行的任何方法,例如:
@AfterSpringLoadComplete
public void init() {}
答案 3 :(得分:1)
我有一个单页应用程序在输入URL时创建了一个HashMap(由我的网页使用),其中包含来自多个数据库的数据。 我在服务器启动时加载了所有内容 -
1- Created ContextListenerClass
public class MyAppContextListener implements ServletContextListener
@Autowired
private MyDataProviderBean myDataProviderBean;
public MyDataProviderBean getMyDataProviderBean() {
return MyDataProviderBean;
}
public void setMyDataProviderBean(MyDataProviderBean MyDataProviderBean) {
this.myDataProviderBean = MyDataProviderBean;
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
}
@Override
public void contextInitialized(ServletContextEvent context) {
System.out.println("ServletContextListener started");
ServletContext sc = context.getServletContext();
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(sc);
MyDataProviderBean MyDataProviderBean = (MyDataProviderBean)springContext.getBean("myDataProviderBean");
Map<String, Object> myDataMap = MyDataProviderBean.getDataMap();
sc.setAttribute("myMap", myDataMap);
}
2-在web.xml中添加以下条目
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.context.listener.MyAppContextListener</listener-class>
</listener>
3-在我的Controller类更新代码中首先检查servletContext中的Map
@RequestMapping(value = "/index", method = RequestMethod.GET)
public String index(@ModelAttribute("model") ModelMap model) {
Map<String, Object> myDataMap = new HashMap<String, Object>();
if (context != null && context.getAttribute("myMap")!=null)
{
myDataMap=(Map<String, Object>)context.getAttribute("myMap");
}
else
{
myDataMap = myDataProviderBean.getDataMap();
}
for (String key : myDataMap.keySet())
{
model.addAttribute(key, myDataMap.get(key));
}
return "myWebPage";
}
当我启动tomcat时会发生这么大的变化,它会在startTime期间加载dataMap并将所有内容放在servletContext中,然后Controller Class使用它来获取已填充的servletContext的结果。
答案 4 :(得分:0)
请在应用上下文被加载(即应用已准备好服务)之后,按照以下步骤进行一些处理。
在下方创建注释,即
@Retention(RetentionPolicy.RUNTIME) @Target(值= {ElementType.METHOD,ElementType.TYPE}) 公共@interface AfterApplicationReady {}
2.Create Under Class是一个侦听器,可在应用就绪状态下进行调用。
@Component
public class PostApplicationReadyListener implements ApplicationListener<ApplicationReadyEvent> {
public static final Logger LOGGER = LoggerFactory.getLogger(PostApplicationReadyListener.class);
public static final String MODULE = PostApplicationReadyListener.class.getSimpleName();
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
try {
ApplicationContext context = event.getApplicationContext();
String[] beans = context.getBeanNamesForAnnotation(AfterAppStarted.class);
LOGGER.info("bean found with AfterAppStarted annotation are : {}", Arrays.toString(beans));
for (String beanName : beans) {
Object bean = context.getBean(beanName);
Class<?> targetClass = AopUtils.getTargetClass(bean);
Method[] methods = targetClass.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(AfterAppStartedComplete.class)) {
LOGGER.info("Method:[{} of Bean:{}] found with AfterAppStartedComplete Annotation.", method.getName(), beanName);
Method currentMethod = bean.getClass().getMethod(method.getName(), method.getParameterTypes());
LOGGER.info("Going to invoke method:{} of bean:{}", method.getName(), beanName);
currentMethod.invoke(bean);
LOGGER.info("Invocation compeleted method:{} of bean:{}", method.getName(), beanName);
}
}
}
} catch (Exception e) {
LOGGER.warn("Exception occured : ", e);
}
}
}
最后,当您在启动日志说明应用程序之前启动Spring应用程序时,将调用监听器。