본 글은 spring web 구동시 IOC 소스코드에 대한 연구를 분석한 글이다
IOC를 공부하려면 먼저 web에서 간단한 웹 프로젝트를 만들어보자.xml
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
문장을 추가하겠습니다. 이는 웹 컨테이너가 시작될 때 먼저 ContextLoaderListener 클래스에 들어간 다음 이를 로드한다는 의미입니다. 클래스 경로 applicationContext.xml 파일에 있습니다. 그런 다음 ContextLoaderListener에 초점을 맞추고 오픈 소스 코드인
/** * Initialize the root web application context. */ @Override public void contextInitialized(ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); } /** * Close the root web application context. */ @Override public void contextDestroyed(ServletContextEvent event) { closeWebApplicationContext(event.getServletContext()); ContextCleanupListener.cleanupAttributes(event.getServletContext()); }
를 클릭합니다. 여기에는 주로 ServletContextListener인터페이스의 두 가지 구현 방법이 포함되어 있습니다. 웹 컨테이너는 먼저 contextInitialized 메서드를 호출하고 tomcat으로 캡슐화된 컨테이너 리소스를 전달한 다음 상위 클래스의 초기화 컨테이너 메서드를 호출합니다.
/*** The root WebApplicationContext instance that this loader manages.*/private WebApplicationContext context;public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { ...........省略// Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. if (this.context == null) { this.context = createWebApplicationContext(servletContext); } if (this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> // determine parent for root web application context, if any. ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } configureAndRefreshWebApplicationContext(cwac, servletContext); } } servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if (ccl != null) { currentContextPerThread.put(ccl, this.context); } ......省略 return this.context; }
이 메서드의 주요 단계는 XmlWebApplicationContext의 루트 컨테이너를 만드는 데 사용되는 createWebApplicationContext 메서드입니다. 이 컨테이너는 servletContextEvent에서 가져옵니다.
loadParentContext 메소드는 상위 컨테이너를 로드하는 데 사용됩니다. 기본 메소드인configureAndRefreshWebApplicationContext는 루트 컨테이너를 구성하고 새로 고치는 데 사용됩니다. 메소드 내에서 가장 중요한 메소드는 가장 중요한 기능을 구현하는 새로 고침 메소드입니다.
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex); // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
prepareRefresh 메소드는 나중에 사용할 환경을 준비하는 데 사용됩니다.
obtainFreshBeanFactory 메소드는 beanFactory를 얻습니다
@Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
실제 반환된 beanFactory는 나중에 xml을 로드하는 데 사용하기 위해 인스턴스화되는 구현 클래스 DefaultListableBeanFactory입니다. 수업.
loadBeanDefinitions는 실제로 클래스를 로드하는 데 사용되는 중요한 메소드입니다. 이전의 메소드는 모두 준비 작업이었습니다.
위 내용은 Spring 웹 시작 시 IOC 소스 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!