How to add a hook to the application context initialization event?
Spring has some standard events which you can handle.
To do that, you must create and register a bean that implements the ApplicationListener
interface, something like this:
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(...)
// ...
}
}
}
You then register this bean within your servlet.xml
or applicationContext.xml
file:
<bean id="eventListenerBean" class="test.pack.age.ApplicationListenerBean" />
and Spring will notify it when the application context is initialized.
In Spring 3 (if you are using this version), the ApplicationListener
class is generic and you can declare the event type that you are interested in, and the event will be filtered accordingly. You can simplify a bit your bean code like this:
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
// now you can do applicationContext.getBean(...)
// ...
}
}
Since Spring 4.2 you can use @EventListener
(documentation)
@Component
class MyClassWithEventListeners {
@EventListener({ContextRefreshedEvent.class})
void contextRefreshedEvent() {
System.out.println("a context refreshed event happened");
}
}
Create your annotation
@Retention(RetentionPolicy.RUNTIME)
public @interface AfterSpringLoadComplete {
}
Create class
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) {
}
}
}
}
Register this class by @Component annotation or in xml
<bean class="ua.adeptius.PostProxyInvokerContextListener"/>
and use annotation where you wan on any method that you want to run after context initialized, like:
@AfterSpringLoadComplete
public void init() {}