SpringMVC 项目启动的加载顺序(一)父类容器的启动
最近在研究Spring MVC项目的启动加载顺序,做一个具体说明:一、web容器的启动1、web项目启动的时候,容器会优先读取web.xml文件,并且先找到<listener></listener>和<context-param></context-param>两个节点;2、容器会创建一
最近在研究Spring MVC项目的启动加载顺序,做一个具体说明:
一、web容器的启动
1、web项目启动的时候,容器会优先读取web.xml文件,并且先找到<listener></listener>和<context-param></context-param>两个节点;
2、容器会创建一个ServlextContext上下文,并解析<context-param></context-param>节点,存入上下文中;
3、容器创建listener实例,并执行listener实例中的contextInitialized(ServletContextEvent sce)方法;
4、执行filter节点信息;
5、最后创建servlet;
二、Web容器启动Spring 容器
web容器启动的时候,SpringMVC配置的ContextLoadListener将会被启动,
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public ContextLoaderListener() { } public ContextLoaderListener(WebApplicationContext context) { super(context); } public void contextInitialized(ServletContextEvent event) { this.initWebApplicationContext(event.getServletContext()); } public void contextDestroyed(ServletContextEvent event) { this.closeWebApplicationContext(event.getServletContext()); ContextCleanupListener.cleanupAttributes(event.getServletContext()); } }
ContextLoadListener会被触发初始化事件,执行initWebApplicationContext方法;
if(this.context == null) { this.context = this.createWebApplicationContext(servletContext); } if(this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext err = (ConfigurableWebApplicationContext)this.context; if(!err.isActive()) { if(err.getParent() == null) { ApplicationContext elapsedTime = this.loadParentContext(servletContext); err.setParent(elapsedTime); } this.configureAndRefreshWebApplicationContext(err, servletContext); } } servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
创建好Context实例后,执行configureAndRefreshWebApplicationContext方法。非常重要的一点,这里会loadParentContext,并且加载ApplicationContext中的bean 资源文件。configureAndRefreshWebApplicationContext方法会执行Context的refresh方法
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { 。。。 this.customizeContext(sc, wac); wac.refresh(); }
Spring加载Bean:
public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); // conetxt 的准备工作 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // 获取bean工厂 this.prepareBeanFactory(beanFactory); // 准备这个上线文需要使用的bean工厂 try { this.postProcessBeanFactory(beanFactory); // Allows post-processing of the bean factory in context subclasses. this.invokeBeanFactoryPostProcessors(beanFactory); // Invoke factory processors registered as beans in the context this.registerBeanPostProcessors(beanFactory); // Register bean processors that intercept bean creation. this.initMessageSource(); this.initApplicationEventMulticaster(); // Initialize event multicaster for this context this.onRefresh(); // Initialize other special beans in specific context subclasses. this.registerListeners(); // Check for listener beans and register them. this.finishBeanFactoryInitialization(beanFactory); // Instantiate all remaining (non-lazy-init) singletons. this.finishRefresh(); // Last step: publish corresponding event. } catch (BeansException var9) { if(this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } }
其中,finishBeanFactoryInitialization方法,
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { if(beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) { beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class)); } if(!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(new StringValueResolver() { public String resolveStringValue(String strVal) { return AbstractApplicationContext.this.getEnvironment().resolvePlaceholders(strVal); } }); } String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); String[] var3 = weaverAwareNames; int var4 = weaverAwareNames.length; for(int var5 = 0; var5 < var4; ++var5) { String weaverAwareName = var3[var5]; this.getBean(weaverAwareName); } beanFactory.setTempClassLoader((ClassLoader)null); beanFactory.freezeConfiguration(); beanFactory.preInstantiateSingletons(); }
到了beanFactory.preInstantiateSingletons();发现类还没有被初始化,继续有到DefaultListableBeanFactory有:
public void preInstantiateSingletons() throws BeansException { ArrayList beanNames = new ArrayList(this.beanDefinitionNames); Iterator var2 = beanNames.iterator(); // Trigger initialization of all non-lazy singleton beans... while(true) { while(true) { String beanName; RootBeanDefinition singletonInstance; do { do { do { if(!var2.hasNext()) { var2 = beanNames.iterator(); while(var2.hasNext()) { beanName = (String)var2.next(); Object singletonInstance1 = this.getSingleton(beanName); if(singletonInstance1 instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton1 = (SmartInitializingSingleton)singletonInstance1; if(System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { smartSingleton1.afterSingletonsInstantiated(); return null; } }, this.getAccessControlContext()); } else { smartSingleton1.afterSingletonsInstantiated(); } } } return; } beanName = (String)var2.next(); singletonInstance = this.getMergedLocalBeanDefinition(beanName); } while(singletonInstance.isAbstract()); } while(!singletonInstance.isSingleton()); } while(singletonInstance.isLazyInit()); if(this.isFactoryBean(beanName)) { final FactoryBean smartSingleton = (FactoryBean)this.getBean("&" + beanName); boolean isEagerInit; if(System.getSecurityManager() != null && smartSingleton instanceof SmartFactoryBean) { isEagerInit = ((Boolean)AccessController.doPrivileged(new PrivilegedAction() { public Boolean run() { return Boolean.valueOf(((SmartFactoryBean)smartSingleton).isEagerInit()); } }, this.getAccessControlContext())).booleanValue(); } else { isEagerInit = smartSingleton instanceof SmartFactoryBean && ((SmartFactoryBean)smartSingleton).isEagerInit(); } if(isEagerInit) { this.getBean(beanName); } } else { this.getBean(beanName); } } } }
其中,
protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if(singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) { Map var4 = this.singletonObjects; synchronized(this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if(singletonObject == null && allowEarlyReference) { ObjectFactory singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName); if(singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject != NULL_OBJECT?singletonObject:null; }
会执行获取bean的实例,并且将bean的实例存下来。
最后,finishRefresh方法会发布Context刷新完成的事件:
protected void finishRefresh() { this.initLifecycleProcessor(); this.getLifecycleProcessor().onRefresh(); this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this))); LiveBeansView.registerApplicationContext(this); }
但是,在执行Bean的实例化之前,是在obtainFreshBeanFactory方法中加载Bean的定义文件的,
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { this.refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = this.getBeanFactory(); if(this.logger.isDebugEnabled()) { this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory); } return beanFactory; }
protected final void refreshBeanFactory() throws BeansException { if(this.hasBeanFactory()) { this.destroyBeans(); this.closeBeanFactory(); } try { DefaultListableBeanFactory ex = this.createBeanFactory(); ex.setSerializationId(this.getId()); this.customizeBeanFactory(ex); this.loadBeanDefinitions(ex); Object var2 = this.beanFactoryMonitor; synchronized(this.beanFactoryMonitor) { this.beanFactory = ex; } } catch (IOException var5) { throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5); } }
如果有BeanFactory存在,先会销毁所有的bean,并且关闭beanFactory,然后在重新创建一个BeanFactory,加载BeanDefinition。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); this.initBeanDefinitionReader(beanDefinitionReader); this.loadBeanDefinitions(beanDefinitionReader); }
LoadBeanDefinitions会从Xml资源读取器中获取信息:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); this.initBeanDefinitionReader(beanDefinitionReader); this.loadBeanDefinitions(beanDefinitionReader); }
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException { String[] configLocations = this.getConfigLocations(); if(configLocations != null) { String[] var3 = configLocations; int var4 = configLocations.length; for(int var5 = 0; var5 < var4; ++var5) { String configLocation = var3[var5]; reader.loadBeanDefinitions(configLocation); } } }
public void setConfigLocations(String... locations) { if(locations != null) { Assert.noNullElements(locations, "Config locations must not be null"); this.configLocations = new String[locations.length]; for(int i = 0; i < locations.length; ++i) { this.configLocations[i] = this.resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }
综上,Bean的定义来源于资源文件,从资源文件上获取定义的加载顺序,从BeanDefinition的加载顺序,确定被实例化的顺序。
obtainFreshBeanFactory()
->refreshBeanFactory()
->loadBeanDefinitions(beanFactory)属于XmlWebApplicationContext
->reader.loadBeanDefinitions(configLocation)
->loadBeanDefinitions(location, null)
->int loadCount = loadBeanDefinitions(resources)
->counter += loadBeanDefinitions(resource)
->loadBeanDefinitions(new EncodedResource(resource))
->doLoadBeanDefinitions(inputSource, encodedResource.getResource())
->registerBeanDefinitions(doc, resource)
->documentReader.registerBeanDefinitions(doc, createReaderContext(resource))
->doRegisterBeanDefinitions(root)
->parseBeanDefinitions(root, this.delegate)
->delegate.parseCustomElement(root)
->parseCustomElement(ele, null)
->handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))
->findParserForElement(element, parserContext).parse(element, parserContext)
->parse(element, parserContext)属于ComponentScanBeanDefinitionParser
关键步骤是parse方法,Spring中自带的Parse有:
常用的componentScan方法:
public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute("base-package"); basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ",; \t\n"); ClassPathBeanDefinitionScanner scanner = this.configureScanner(parserContext, element); Set beanDefinitions = scanner.doScan(basePackages); this.registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
doScan方法返回的是一个Set集合,
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); LinkedHashSet beanDefinitions = new LinkedHashSet(); String[] var3 = basePackages; int var4 = basePackages.length; for(int var5 = 0; var5 < var4; ++var5) { String basePackage = var3[var5]; Set candidates = this.findCandidateComponents(basePackage); Iterator var8 = candidates.iterator(); while(var8.hasNext()) { BeanDefinition candidate = (BeanDefinition)var8.next(); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if(candidate instanceof AbstractBeanDefinition) { this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName); } if(candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate); } if(this.checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); this.registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
在查找候选的定义方法中有:
public Set<BeanDefinition> findCandidateComponents(String basePackage) { LinkedHashSet candidates = new LinkedHashSet(); try { String ex = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = this.resourcePatternResolver.getResources(ex); boolean traceEnabled = this.logger.isTraceEnabled(); boolean debugEnabled = this.logger.isDebugEnabled(); Resource[] var7 = resources; int var8 = resources.length; for(int var9 = 0; var9 < var8; ++var9) { Resource resource = var7[var9]; if(traceEnabled) { this.logger.trace("Scanning " + resource); } if(resource.isReadable()) { try { MetadataReader ex1 = this.metadataReaderFactory.getMetadataReader(resource); if(this.isCandidateComponent(ex1)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(ex1); sbd.setResource(resource); sbd.setSource(resource); if(this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) { if(debugEnabled) { this.logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else if(debugEnabled) { this.logger.debug("Ignored because not a concrete top-level class: " + resource); } } else if(traceEnabled) { this.logger.trace("Ignored because not matching any filter: " + resource); } } catch (Throwable var13) { throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var13); } } else if(traceEnabled) { this.logger.trace("Ignored because not readable: " + resource); } } return candidates; } catch (IOException var14) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var14); } }
直接将ScannedGenericBeanDefinition加入里Set集合,这个类的继承关系有:
更多推荐
所有评论(0)