Jak dodać hook do zdarzenia inicjalizacji kontekstu aplikacji?
Dla zwykłego Servletu, można chyba zadeklarować context listener , ale dla Springa MVC by to ułatwiło?
Ponadto, jeśli zdefiniuję słuchacz kontekstu i będę musiał uzyskać dostęp do fasoli zdefiniowanych w moim servlet.xml
lub applicationContext.xml
, Jak uzyskam do nich dostęp?
5 answers
Wiosna ma kilka standardowych wydarzeń, które można obsłużyć.
Aby to zrobić, musisz utworzyć i zarejestrować bean, który implementuje interfejs ApplicationListener
, coś w tym stylu:
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(...)
// ...
}
}
}
Następnie rejestrujesz tę fasolkę w swoim pliku servlet.xml
lub applicationContext.xml
:
<bean id="eventListenerBean" class="test.pack.age.ApplicationListenerBean" />
I Spring powiadomi go, gdy zostanie zainicjowany kontekst aplikacji.
W Spring 3 (Jeśli używasz tej wersji),ApplicationListener
klasa jest generic i można zadeklarować typ zdarzenia które Cię interesują, a wydarzenie zostanie odpowiednio filtrowane. Możesz uprościć trochę swój kod bean w ten sposób:
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
// now you can do applicationContext.getBean(...)
// ...
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-24 16:38:13
Od wiosny 4.2 można używać @EventListener
(Dokumentacja )
@Component
class MyClassWithEventListeners {
@EventListener({ContextRefreshedEvent.class})
void contextRefreshedEvent() {
System.out.println("a context refreshed event happened");
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-14 16:00:20
Utwórz swoją adnotację
@Retention(RetentionPolicy.RUNTIME)
public @interface AfterSpringLoadComplete {
}
Utwórz klasę
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) {
}
}
}
}
Zarejestruj tę klasę przez adnotację @ Component lub w xml
<bean class="ua.adeptius.PostProxyInvokerContextListener"/>
I używaj adnotacji tam, gdzie chcesz użyć dowolnej metody, którą chcesz uruchomić po zainicjalizowaniu kontekstu, np:
@AfterSpringLoadComplete
public void init() {}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-03 17:36:24
Miałem jednostronicową aplikację przy wprowadzaniu adresu URL, która tworzyła Hashmapę (używaną przez moją stronę), która zawierała dane z wielu baz danych. Zrobiłem następujące rzeczy, aby załadować wszystko podczas startu serwera -
1-Utworzony 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-dodany poniżej wpis W web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.context.listener.MyAppContextListener</listener-class>
</listener>
3-w mojej klasie kontrolera zaktualizowany kod, aby najpierw sprawdzić mapę w servletContext
@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";
}
Przy tak dużej zmianie kiedy uruchamiam tomcat ładuje się dataMap podczas startTime i umieszcza wszystko w servletContext, który jest następnie używany przez klasę kontrolera, aby uzyskać wyniki z już wypełnionego servletContext .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-30 06:43:07
Wykonaj poniższy krok, aby wykonać pewne przetwarzanie po załadowaniu kontekstu aplikacji, tzn.
-
Utwórz poniższą adnotację tj.
@Retention (RetentionPolicy.RUNTIME) @Target (value ={ElementType.Metoda, ElementType.Typ}) public @ interface after Applicationready {}
2.Utwórz poniżej klasę, która jest listenerem, który otrzyma wywołanie w stanie gotowości aplikacji.
@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);
}
}
}
Wreszcie po uruchomieniu aplikacji wiosennej tuż przed uruchomieniem logu zostanie wywołany Twój słuchacz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-04 16:43:45