애플리케이션 컨텍스트 초기화 이벤트에 후크를 추가하는 방법은 무엇입니까?
일반 서블릿의 경우 컨텍스트 청취자를 선언할 수 있지만 Spring MVC의 경우 이를 더 쉽게 할 수 있을까요?
게다가, 만약 내가 문맥 청취자를 정의하고 내가 내게 정의한 콩에 접근해야 한다면,servlet.xml
또는applicationContext.xml
어떻게 접근해야 하나요?
봄에는 당신이 처리할 수 있는 몇 가지 표준 이벤트가 있습니다.
그러기 위해서는 다음을 구현하는 빈을 생성하고 등록해야 합니다.ApplicationListener
인터페이스, 다음과 같은 것:
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 id="eventListenerBean" class="test.pack.age.ApplicationListenerBean" />
애플리케이션 컨텍스트가 초기화되면 Spring에서 이를 알려줍니다.
Spring 3(이 버전을 사용하는 경우)에서는 클래스가 일반적이므로 관심 있는 이벤트 유형을 선언할 수 있으며 그에 따라 이벤트가 필터링됩니다.다음과 같이 빈 코드를 조금 단순화할 수 있습니다.
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
// now you can do applicationContext.getBean(...)
// ...
}
}
4.2 봄부터 사용할 수 있습니다.@EventListener
(해석)
@Component
class MyClassWithEventListeners {
@EventListener({ContextRefreshedEvent.class})
void contextRefreshedEvent() {
System.out.println("a context refreshed event happened");
}
}
주석 작성
@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() {}
응용 프로그램 컨텍스트를 로드한 후(예: 응용 프로그램을 서비스할 준비가 된 후) 다음 단계에 따라 처리하십시오.
아래에 주석을 만듭니다.
@보존(보존 정책).런타임) @Target(값 = {ElementType}.방법, 요소 유형.TYPE} public @ApplicationReady {} 후 인터페이스
2.응용 프로그램 준비 상태에서 호출을 수신하는 수신기인 Below 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 응용 프로그램을 시작하면 수신기가 호출됩니다.
URL을 입력할 때 여러 데이터베이스의 데이터를 포함하는 해시맵(웹 페이지에서 사용)을 만드는 단일 페이지 응용 프로그램이 있었습니다.서버 시작 시간에 모든 것을 로드하기 위해 다음과 같은 작업을 수행했습니다.
1 - 작성된 컨텍스트 수신기 클래스
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 - 먼저 서블릿 컨텍스트에서 맵을 확인하기 위해 컨트롤러 클래스에서 코드가 업데이트되었습니다.
@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에 저장합니다. 그러면 컨트롤러 클래스에서 이미 채워진 servletContext의 결과를 가져오는 데 사용됩니다.
언급URL : https://stackoverflow.com/questions/8686507/how-to-add-a-hook-to-the-application-context-initialization-event
'programing' 카테고리의 다른 글
Android: 작업 표시줄의 사용자 지정 레이아웃에서 왼쪽 여백 제거 (0) | 2023.08.22 |
---|---|
각도 - 관찰 가능한 비동기 파이프 사용각도 - 관찰 가능한 비동기 파이프 사용html의 로컬 변수에 바인딩합니다.html의 로컬 변수에 바인딩합니다.안녕하세요. 많은 속성(이름, 제목, 주소...)을 .. (0) | 2023.08.22 |
Gitflow 릴리스 분기 및 태그 - "v" 접두사 사용 여부와 상관없이 (0) | 2023.08.22 |
최대 높이의 자식: 100%가 상위 항목으로 넘칩니다. (0) | 2023.08.22 |
공유 기본 설정에 어레이 목록 저장 (0) | 2023.08.17 |