如何将钩子添加到应用程序上下文初始化事件中?
如何将钩子添加到应用程序上下文初始化事件中?
对于普通的Servlet,我想你可以声明一个上下文监听器,但对于Spring MVC,Spring会让这变得更容易吗?
此外,如果我定义了一个上下文监听器,然后需要访问我在servlet.xml
或applicationContext.xml
中定义的bean,我该如何获得访问权限?
如何向应用程序上下文初始化事件添加一个钩子?
Spring有一些标准事件可以处理。为了做到这一点,你必须创建并注册一个实现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 { public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent) { ApplicationContext applicationContext = ((ContextRefreshedEvent) event).getApplicationContext(); // 现在你可以使用applicationContext.getBean(...) // ... } } }
然后在servlet.xml或applicationContext.xml文件中注册这个bean:
Spring会在应用程序上下文初始化时通知它。
在Spring 3中(如果你使用的是这个版本),ApplicationListener类是泛型的,你可以声明你感兴趣的事件类型,事件将被过滤。你可以简化一下你的bean代码,像这样:
public class ApplicationListenerBean implements ApplicationListener{ public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext applicationContext = event.getApplicationContext(); // 现在你可以使用applicationContext.getBean(...) // ... } }
如果你使用注解和声明了两个类,你有任何想法会发生什么?非注解(XML)和两个?它们会按照声明的顺序触发吗?
只是提供信息,对于context started事件,可以使用ContextStartedEvent。
Sambhav:是的,这是正确的,但也必须提到一下区别。看这里:stackoverflow.com/questions/5728376/…和这里:forum.spring.io/forum/spring-projects/container/…
根据Spring文档:“从Spring 3.0开始,ApplicationListener可以通用地声明它感兴趣的事件类型。当与Spring ApplicationContext一起注册时,事件将被相应地过滤,只有匹配的事件对象才会调用监听器。”因此,你可以通过实现ApplicationListener
当前的Spring事件文档。
是的,需要实现ApplicationListener
需要在类的上方添加``。
问题的出现原因是需要在应用程序上下文初始化事件中添加一个钩子(hook)。
解决方法是首先创建一个自定义的注解`AfterSpringLoadComplete`,然后创建一个`PostProxyInvokerContextListener`类来实现`ApplicationListener
使用方法是在需要在应用程序上下文初始化后运行的方法上添加`AfterSpringLoadComplete`注解。
以下是完整的代码示例:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) public @interface AfterSpringLoadComplete { } public class PostProxyInvokerContextListener implements ApplicationListener{ ConfigurableListableBeanFactory factory; 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) { } } } } // 注册该类到应用程序上下文中 // 使用注解在需要初始化后运行的方法上 public class YourClass { @AfterSpringLoadComplete public void init() { // 这个方法会在应用程序上下文初始化后运行 } }
通过以上步骤,我们可以在应用程序上下文初始化事件中添加一个钩子(hook)。
从Spring 4.2版本开始,可以使用ContextRefreshedEvent来监听应用程序上下文初始化事件。在这个问题中,用户想要知道如何向应用程序上下文初始化事件中添加一个钩子,并且需要打印出属性等信息。用户提供了一个示例代码,但是他们发现这个方法似乎没有参数可以用来打印属性等信息。
解决方法是,只需要将ContextRefreshedEvent作为参数添加到方法中即可,而不是使用注解参数。下面是修改后的示例代码:
class MyClassWithEventListeners { void contextRefreshedEvent(ContextRefreshedEvent event) { System.out.println("a context refreshed event happened"); // 打印属性等信息 System.out.println(event.getApplicationContext().getEnvironment().getProperty("property.name")); } }
通过这种方式,用户就可以在应用程序上下文初始化事件发生时打印出属性等信息了。