因为WebApplicationContext 需要ServletContext 实例,也就是说它必须在拥有Web 容器的前提下才能完成启动的工作。有过Web 开发经验的读者都知道可以在web.xml 中配置自启动的Servlet 或定义Web 容器监听器(ServletContextListener),借助这两者中的任何一个,我们就可以完成启动Spring Web 应用上下文的工作。
Spring 分别提供了用于启动WebApplicationContext 的Servlet 和Web 容器监听器:
org.springframework.web.context.ContextLoaderServlet;
org.springframework.web.context.ContextLoaderListener。
两者的内部都实现了启动WebApplicationContext 实例的逻辑,我们只要根据Web 容器的具体情况选择两者之一,并在web.xml 中完成配置就可以了。
- <span style="font-size:18px;"> ContextLoader
- /**
- * Initialize the root web application context.
- */
- @Override
- public void contextInitialized(ServletContextEvent event) {
- initWebApplicationContext(event.getServletContext());
- }</span>
- <span style="font-size:18px;">ContextLoader
- public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
- if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
- throw new IllegalStateException(
- "Cannot initialize context because there is already a root application context present - " +
- "check whether you have multiple ContextLoader* definitions in your web.xml!");
- }
- Log logger = LogFactory.getLog(ContextLoader.class);
- servletContext.log("Initializing Spring root WebApplicationContext");
- if (logger.isInfoEnabled()) {
- logger.info("Root WebApplicationContext: initialization started");
- }
- long startTime = System.currentTimeMillis();
- try {
- // Store context in local instance variable, to guarantee that
- // it is available on ServletContext shutdown.
- if (this.context == null) {
- this.context = createWebApplicationContext(servletContext); //这里根据ServletContext创建Spring容器(在这里创建的是XmlWebApplicationContext)
- }
- 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); //这里进行WebApplicationContext的配置工作,其中包括把servletContext和Spring容器关联起来,以及将配置文件(applicationContext.xml)加入到容器中
- }
- }
- 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);
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
- WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
- }
- if (logger.isInfoEnabled()) {
- long elapsedTime = System.currentTimeMillis() - startTime;
- logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
- }
- return this.context;
- }
- catch (RuntimeException ex) {
- logger.error("Context initialization failed", ex);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
- throw ex;
- }
- catch (Error err) {
- logger.error("Context initialization failed", err);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
- throw err;
- }
- }</span>
- <span style="font-size:18px;">//ContextLoader
- protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
- Class<?> contextClass = determineContextClass(sc); //返回WebApplicationContext实现类使用,默认XmlWebApplicationContext或如果指定一个自定义上下文类。
- if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
- throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
- "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
- }
- return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
- }</span>
- <span style="font-size:18px;">//web.xml
- <!-- 如果配置了contextClass上下文参数,就会用参数所指定的WebApplicationContext实现类初始话容器 -->
- <context-param>
- <param-name>contextClass</param-name>
- <param-value>
- org.springframework.web.context.support.XmlWebApplicationContext
- </param-value>
- </context-param></span>
接着,我们回到initWebApplicationContext(),其中调用的configureAndRefreshWebApplicationContext(cwac, servletContext);我们看一下他的实现
- <span style="font-size:18px;">protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
- if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
- // The application context id is still set to its original default value
- // -> assign a more useful id based on available information
- String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
- if (idParam != null) {
- wac.setId(idParam); //这里设置WebApplicationContext的id值为contextId也就是我们浏览器访问的localhost:8080/01/中的01
- }
- else {
- // Generate default id...
- wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
- ObjectUtils.getDisplayString(sc.getContextPath()));
- }
- }
- wac.setServletContext(sc);
- String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);//这里设置Web.xml中配置的contextConfigLocation参数,也就是配置文件applicationContext.xml了
- if (initParameter != null) {
- wac.setConfigLocation(initParameter);
- }
- customizeContext(sc, wac);
- wac.refresh(); //加载刚才的配置文件applicationContext.xml,以及bean的实例化
- }</span>
- <span style="font-size:18px;">//XmlWebApplicationContext
- @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) {
- // Destroy already created singletons to avoid dangling resources.
- destroyBeans();
- // Reset 'active' flag.
- cancelRefresh(ex);
- // Propagate exception to caller.
- throw ex;
- }
- }
- }</span>
这个方法就是配置Spirng Web容器,根据applicationContext.xml实例化类的重中之重
接着我们继续看WebApplicationContext的refresh()方法
先看一下他的顺序图
- //AbstractApplicationContext XmlWebApplicationContext的父类
- @Override
- public void refresh() throws BeansException, IllegalStateException {
- synchronized (this.startupShutdownMonitor) {
- // 准备容器的更新
- prepareRefresh();
- // 告诉子类刷新内部bean工厂
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
- // 配置factory的标准容器特征,包括classloader和postprocessor等
- prepareBeanFactory(beanFactory);
- try {
- // 修改应用程序上下文的内部bean工厂标准后初始化。所有bean定义将被加载,但没有实例化bean。这允许在某些ApplicationContext实现类注册特殊BeanPostProcessors
- postProcessBeanFactory(beanFactory);
- // 实例化<span style="font-family: Arial, Helvetica, sans-serif;">所有注册到</span><span style="font-family: Arial, Helvetica, sans-serif;">BeanFactoryPostProcessor的bean,如果有次序,就按照次序实例化,必须在单例实例化之前</span>
- invokeBeanFactoryPostProcessors(beanFactory);
- // 实例化并调用所有注册BeanPostProcessor的bean<span style="font-family: Arial, Helvetica, sans-serif;">,如果有次序,就按照次序实例化。</span> 必须在 application bean的实例化之前调用。
- registerBeanPostProcessors(beanFactory);
- // 实例化MessageSource()
- initMessageSource();
- // 实例化ApplicationEventMulticaster
- initApplicationEventMulticaster();
- // 实例化容器中特殊的类
- onRefresh();
- // 注册实现ApplicationListener的listener
- registerListeners();
- // 完成容器的beanFactory的实例化,初始化所有剩余单例bean
- finishBeanFactoryInitialization(beanFactory);
- //调用LifecycleProcessor的onRefresh()以及发布 org.springframework.context.event.ContextRefreshedEvent。
- finishRefresh();
- }
- catch (BeansException ex) {
- // Destroy already created singletons to avoid dangling resources.
- destroyBeans();
- // Reset 'active' flag.
- cancelRefresh(ex);
- // Propagate exception to caller.
- throw ex;
- }
- }
- }
先看refresh()方法中的prepareBeanFactory()
- //AbstractApplicationContext
- protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
- // Tell the internal bean factory to use the context's class loader etc.
- beanFactory.setBeanClassLoader(getClassLoader());
- beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
- beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
- // Configure the bean factory with context callbacks.
- beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
- beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
- beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
- beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
- beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
- beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
- // BeanFactory interface not registered as resolvable type in a plain factory.
- // MessageSource registered (and found for autowiring) as a bean.
- beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
- beanFactory.registerResolvableDependency(ResourceLoader.class, this);
- beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
- beanFactory.registerResolvableDependency(ApplicationContext.class, this);
- // Detect a LoadTimeWeaver and prepare for weaving, if found.
- if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
- beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
- // Set a temporary ClassLoader for type matching.
- beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
- }
- // Register default environment beans.
- if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
- beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
- }
- if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
- beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
- }
- if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
- beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
- }
- }
这里都是为beanFactory(也就是DefaultListableBeanFactory)设置一些属性
我们再看一下ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();里面的操作
- //AbstractApplicationContext
- /**
- * Tell the subclass to refresh the internal bean factory.
- * @return the fresh BeanFactory instance
- * @see #refreshBeanFactory()
- * @see #getBeanFactory()
- */
- protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
- refreshBeanFactory(); //创建一个DefaultListableBeanFactory,并加载类,实例化为对应的BeanDefinition
- ConfigurableListableBeanFactory beanFactory = getBeanFactory(); //取得该DefaultListableBeanFactory,后面返回
- if (logger.isDebugEnabled()) {
- logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
- }
- return beanFactory;
- }
我们在看一下refreshBeanFactory()
- //AbstractRefreshableApplicationContext
- /**
- * This implementation performs an actual refresh of this context's underlying
- * bean factory, shutting down the previous bean factory (if any) and
- * initializing a fresh bean factory for the next phase of the context's lifecycle.
- */
- @Override
- protected final void refreshBeanFactory() throws BeansException {
- if (hasBeanFactory()) {
- destroyBeans();
- closeBeanFactory();
- }
- try {
- DefaultListableBeanFactory beanFactory = createBeanFactory(); //这里创建了一个DefaultListableBeanFactory,供后面实例化bean
- 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);
- }
- }
我们在进入看loadBeanDefinitions()
- //XmlWebApplicationContext
- /**
- * Loads the bean definitions via an XmlBeanDefinitionReader.
- * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
- * @see #initBeanDefinitionReader
- * @see #loadBeanDefinitions
- */
- @Override
- protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
- // Create a new XmlBeanDefinitionReader for the given BeanFactory.
- XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
- // 这里为beanDefinitionReader配置容器的属性
- beanDefinitionReader.setEnvironment(this.getEnvironment());
- beanDefinitionReader.setResourceLoader(this);
- beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
- initBeanDefinitionReader(beanDefinitionReader); //这个方法其实是空的,留给以后subclass去实现
- loadBeanDefinitions(beanDefinitionReader); //这里开始加载BeanDefinition了
- }
我们再进入loadBeanDefinitions()
- //XmlWebApplicationContext
- /**
- * Load the bean definitions with the given XmlBeanDefinitionReader.
- * <p>The lifecycle of the bean factory is handled by the refreshBeanFactory method;
- * therefore this method is just supposed to load and/or register bean definitions.
- * <p>Delegates to a ResourcePatternResolver for resolving location patterns
- * into Resource instances.
- * @throws java.io.IOException if the required XML document isn't found
- * @see #refreshBeanFactory
- * @see #getConfigLocations
- * @see #getResources
- * @see #getResourcePatternResolver
- */
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
- String[] configLocations = getConfigLocations(); //这里开始读取配置文件了,就是我们之前的applicationContext.xml的配置文件了
- if (configLocations != null) {
- for (String configLocation : configLocations) {
- reader.loadBeanDefinitions(configLocation); //这里就开始加载配置文件中的bean了,实例化成beandefinition
- }
- }
- }
reader.loadBeanDefinitions(configLocation)
- //AbstractBeanDefinitionReader
- public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
- ResourceLoader resourceLoader = getResourceLoader();
- if (resourceLoader == null) {
- throw new BeanDefinitionStoreException(
- "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
- }
- if (resourceLoader instanceof ResourcePatternResolver) {
- // Resource pattern matching available.
- try {
- Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
- int loadCount = loadBeanDefinitions(resources); //这里就是加载了,返回加载类的数目
- if (actualResources != null) {
- for (Resource resource : resources) {
- actualResources.add(resource);
- }
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
- }
- return loadCount;
- }
- catch (IOException ex) {
- throw new BeanDefinitionStoreException(
- "Could not resolve bean definition resource pattern [" + location + "]", ex);
- }
- }
- else {
- // Can only load single resources by absolute URL.
- Resource resource = resourceLoader.getResource(location);
- int loadCount = loadBeanDefinitions(resource);
- if (actualResources != null) {
- actualResources.add(resource);
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
- }
- return loadCount;
- }
- }
接着我们再看refresh()中的invokeBeanFactoryPostProcessors()
他最后交给DefaultListableBeanFactory去实例话那些注册到BeanFactoryPostProcessor的那些类
- //DefaultListableBeanFactory
- private String[] doGetBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
- List<String> result = new ArrayList<String>();
- // 获得之前加载的类名
- String[] beanDefinitionNames = getBeanDefinitionNames();
- for (String beanName : beanDefinitionNames) {//遍历之前加载的全部类,并从中找出注册到<span style="font-family: 微软雅黑; font-size: 14.399999618530273px;">BeanFactoryPostProcessor的那些类,把他们加入到result,为下面实例化</span>
- // Only consider bean as eligible if the bean name
- // is not defined as alias for some other bean.
- if (!isAlias(beanName)) {
- try {
- RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
- // Only check bean definition if it is complete.
- if (!mbd.isAbstract() && (allowEagerInit ||
- ((mbd.hasBeanClass() || !mbd.isLazyInit() || this.allowEagerClassLoading)) &&
- !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
- // In case of FactoryBean, match object created by FactoryBean.
- boolean isFactoryBean = isFactoryBean(beanName, mbd);
- boolean matchFound = (allowEagerInit || !isFactoryBean || containsSingleton(beanName)) &&
- (includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type);
- if (!matchFound && isFactoryBean) {
- // In case of FactoryBean, try to match FactoryBean instance itself next.
- beanName = FACTORY_BEAN_PREFIX + beanName;
- matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
- }
- if (matchFound) {
- result.add(beanName);
- }
- }
- }
- catch (CannotLoadBeanClassException ex) {
- if (allowEagerInit) {
- throw ex;
- }
- // Probably contains a placeholder: let's ignore it for type matching purposes.
- if (this.logger.isDebugEnabled()) {
- this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
- }
- onSuppressedException(ex);
- }
- catch (BeanDefinitionStoreException ex) {
- if (allowEagerInit) {
- throw ex;
- }
- // Probably contains a placeholder: let's ignore it for type matching purposes.
- if (this.logger.isDebugEnabled()) {
- this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
- }
- onSuppressedException(ex);
- }
- }
- }
这里,后面的refresh()的registerBeanPostProcessors(beanFactory)实例化过程是和之前的invokeBeanFactoryPostProcessors()一样的。
我们再来看refresh()的initMessageSource()
- //AbstractApplicationContext
- protected void initMessageSource() {
- ConfigurableListableBeanFactory beanFactory = getBeanFactory();
- if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { //如果配置文件applicationContext.xml有配置messageSource,就根据配置文件实例化
- this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
- // Make MessageSource aware of parent MessageSource.
- if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
- HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
- if (hms.getParentMessageSource() == null) {
- // Only set parent context as parent MessageSource if no parent MessageSource
- // registered already.
- hms.setParentMessageSource(getInternalParentMessageSource());
- }
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Using MessageSource [" + this.messageSource + "]");
- }
- }
- else {
- // Use empty MessageSource to be able to accept getMessage calls.
- DelegatingMessageSource dms = new DelegatingMessageSource();
- dms.setParentMessageSource(getInternalParentMessageSource());
- this.messageSource = dms;
- beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
- if (logger.isDebugEnabled()) {
- logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
- "': using default [" + this.messageSource + "]");
- }
- }
- }
这里就是根据我们在配置文件applicationContext.xml中的时候有messagesource的配置,有的话就是实例化,没有的话就实例化一个DelegatingMessageSource,再把他设置到容器,在把他注册到单例集合中
接着,refresh()的initApplicationEventMulticaster()就是初始化ApplicationEventMulticaster。如果我们自己没有配置自定义的ApplicationEventMulticaster那就使用SimpleApplicationEventMulticaster
实例化思路还是和实例化messageSource差不多,都是从配置文件优先,如果没有明确配置就用默认的
接着,我们再来看refresh()的registerListener(),他就是先注册静态的容器本来级就应该有的类,然后在从我们之前加载的类中筛选listener,帅选实例化过程和之前的invokeBeanFactoryPostProcessors()实例化过程是一样的,接着在把listener加入到上面实例化的ApplicationEventMulticaster(它其实就是一个listener容器)中
- //AbstractApplicationContext
- protected void registerListeners() {
- // Register statically specified listeners first.
- for (ApplicationListener<?> listener : getApplicationListeners()) {
- getApplicationEventMulticaster().addApplicationListener(listener);
- }
- // Do not initialize FactoryBeans here: We need to leave all regular beans
- // uninitialized to let post-processors apply to them!
- String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
- for (String lisName : listenerBeanNames) {
- getApplicationEventMulticaster().addApplicationListenerBean(lisName);
- }
- }
接着就是refresh()的finishBeanFactoryInitialization()
- //AbstractApplicationContext
- /**
- * Finish the initialization of this context's bean factory,
- * initializing all remaining singleton beans.
- */
- protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
- // Initialize conversion service for this context.
- if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
- beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
- beanFactory.setConversionService(
- beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
- }
- // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
- String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
- for (String weaverAwareName : weaverAwareNames) {
- getBean(weaverAwareName);
- }
- // Stop using the temporary ClassLoader for type matching.
- beanFactory.setTempClassLoader(null);
- // 允许缓存所有将不会被修改或进一步后期处理的bean定义元数据
- beanFactory.freezeConfiguration();
- // 实例化所有剩下的单例bean
- beanFactory.preInstantiateSingletons();
- }
再接着,refresh()的finishRefresh()
最后回到上篇博客中的initWebApplicationContext中
- //ClassLoader
- public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
- if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
- throw new IllegalStateException(
- "Cannot initialize context because there is already a root application context present - " +
- "check whether you have multiple ContextLoader* definitions in your web.xml!");
- }
- Log logger = LogFactory.getLog(ContextLoader.class);
- servletContext.log("Initializing Spring root WebApplicationContext");
- if (logger.isInfoEnabled()) {
- logger.info("Root WebApplicationContext: initialization started");
- }
- long startTime = System.currentTimeMillis();
- try {
- // 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);
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
- WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
- }
- if (logger.isInfoEnabled()) {
- long elapsedTime = System.currentTimeMillis() - startTime;
- logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
- }
- return this.context;
- }
- catch (RuntimeException ex) {
- logger.error("Context initialization failed", ex);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
- throw ex;
- }
- catch (Error err) {
- logger.error("Context initialization failed", err);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
- throw err;
- }
- }
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); 将容器设置为ServletContext的属性,之前我们已经这是了ServletContext作为WebApplicationContext的属性,于是,两者相关联,可以通过ServletContext.getAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)获得容器
自此,Spring容器创建完毕