如何将钩子添加到应用程序上下文初始化事件中?

12 浏览
0 Comments

如何将钩子添加到应用程序上下文初始化事件中?

对于普通的Servlet,我想你可以声明一个上下文监听器,但对于Spring MVC,Spring会让这变得更容易吗?

此外,如果我定义了一个上下文监听器,然后需要访问我在servlet.xmlapplicationContext.xml中定义的bean,我该如何获得访问权限?

0
0 Comments

如何向应用程序上下文初始化事件添加一个钩子?

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来替换instanceof检查。

当前的Spring事件文档。

是的,需要实现ApplicationListener

需要在类的上方添加``。

0
0 Comments

问题的出现原因是需要在应用程序上下文初始化事件中添加一个钩子(hook)。

解决方法是首先创建一个自定义的注解`AfterSpringLoadComplete`,然后创建一个`PostProxyInvokerContextListener`类来实现`ApplicationListener`接口,该类在应用程序上下文刷新完成后会被调用。在`onApplicationEvent`方法中,通过获取应用程序上下文和Bean的定义名称,遍历所有的Bean。对于每个Bean,检查它是否有`AfterSpringLoadComplete`注解,如果有,则获取该Bean的实例,并通过反射调用标有注解的方法。最后,将`PostProxyInvokerContextListener`类注册到应用程序上下文中。

使用方法是在需要在应用程序上下文初始化后运行的方法上添加`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)。

0
0 Comments

从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"));
    }
}

通过这种方式,用户就可以在应用程序上下文初始化事件发生时打印出属性等信息了。

0