Spring Source code -- Spring container initialization 2

Source: Internet
Author: User

This blog is a continuation of Spring container initialization 1, the source code of the previous blog. Before reading this blog, let's take a look at the previous one.


Next, let's continue to look at the refresh () method of WebApplicationContext.

First look at his sequence diagram





<喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHA + combine = "brush: java;"> // The parent class of AbstractApplicationContext XmlWebApplicationContext @ Overridepublic void refresh () throws BeansException, IllegalStateException {synchronized (this. startupShutdownMonitor) {// prepare the container's update prepareRefresh (); // notify the subclass to refresh the internal bean factory export ablelistablebeanfactory beanFactory = obtainFreshBeanFactory (); // configure the standard container features of the factory, including classloader, postprocessor, and other prepareBeanFac Modify (beanFactory); try {// modify the internal bean Factory standard of the application context and initialize it. All bean definitions will be loaded, but bean is not instantiated. This allows special BeanPostProcessorspostProcessBeanFactory (beanFactory) to be registered in certain ApplicationContext implementation classes; // instantiate all beans registered to BeanFactoryPostProcessor. If there is an order, they are instantiated in order, invokeBeanFactoryPostProcessors (beanFactory); // instantiate and call all beans registered with BeanPostProcessor. If there is an order, it is instantiated in order. It must be called before the application bean is instantiated. RegisterBeanPostProcessors (beanFactory); // instantiate MessageSource () initMessageSource (); // instantiate ApplicationEventMulticasterinitApplicationEventMulticaster (); // instantiate the special class onRefresh () in the container (); // register the listenerregisterListeners () that implements ApplicationListener; // instantiate the beanFactory of the container and initialize all the remaining Singleton beanfinisincluanfactoryinitialization (beanFactory); // call the onRefresh () and org. springframework. context. event. contextRefreshedEv Ent. FinishRefresh ();} catch (BeansException ex) {// Destroy already created singletons to avoid dangling resources. destroyBeans (); // Reset 'active' flag. cancelRefresh (ex); // Propagate exception to caller. throw ex ;}}}


Let's take a look at the operations in ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory ();

// AbstractApplicationContext/*** Tell the subclass to refresh the internal bean factory. * @ return the fresh BeanFactory instance * @ see # refreshBeanFactory () * @ see # getBeanFactory () */protected export obtainFreshBeanFactory () {refreshBeanFactory (); // create a defalistlistablebeanfactory, load the class and instantiate it as the corresponding beandefinitionexcepablelistablebeanfactory beanFactory = getBeanFactory (); // get the defalistlistablebeanfactory, and then return if (logger. isDebugEnabled () {logger. debug ("Bean factory for" + getDisplayName () + ":" + beanFactory);} return beanFactory ;}

Let's take a look at 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. * // @ Overrideprotected final void refreshBeanFactory () throws BeansException {if (hasBeanFactory () {destroyBeans (); closeBeanFactory () ;}try {describeanfactory = createBeanFactory (); // here a defalistlistablebeanfactory is created for beanbeanFactory to be instantiated later. 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 );}}

We are reading loadBeanDefinitions ()

// XmlWebApplicationContext/*** Loads the bean definitions via an XmlBeanDefinitionReader. * @ see org. springframework. beans. factory. xml. required * @ see # required * @ see # loadBeanDefinitions */@ Overrideprotected void loadBeanDefinitions (describeanfactory) throws BeansException, IOException {// Create a new rule for the given beanFactory. xmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader (beanFactory); // configure the container attribute beanDefinitionReader for beanDefinitionReader. setEnvironment (this. getEnvironment (); beanDefinitionReader. setResourceLoader (this); beanDefinitionReader. setEntityResolver (new ResourceEntityResolver (this); initBeanDefinitionReader (beanDefinitionReader); // this method is actually empty and left to subclass to implement loadBeanDefinitions (beanDefinitionReader ); // BeanDefinition is started here}

Let's go to loadBeanDefinitions ()

// XmlWebApplicationContext/*** Load the bean definitions with the given XmlBeanDefinitionReader .*

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 .*

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 # Annotations */protected void loadBeanDefinitions (XmlBeanDefinitionReader reader) throws IOException {String [] configLocations = getCon FigLocations (); // read the configuration file, which is the configuration file of our previous applicationContext. xml. if (configLocations! = Null) {for (String configLocation: configLocations) {reader. loadBeanDefinitions (configLocation); // load the bean in the configuration file and convert the instance to beandefinition }}}


Reader. loadBeanDefinitions (configLocation)

// AbstractBeanDefinitionReaderpublic int loadBeanDefinitions (String location, Set
 
  
ActualResources) throws handler {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 = (Resou RcePatternResolver) 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 ("cocould not resolve bean definition resource pattern [" + location + "]", ex) ;}} else {// Can only load single res Ources 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 ;}}
 

Return to prepareBeanFactory () in the refresh () method ()

//AbstractApplicationContextprotected 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());}}
Here, we set some attributes for beanFactory (that is, DefaultListableBeanFactory ).


Next, let's look at invokeBeanFactoryPostProcessors () in refresh ()


He finally handed it to defalistlistablebeanfactory To Go To The instance and the classes registered to BeanFactoryPostProcessor


// DefaultListableBeanFactoryprivate String [] doGetBeanNamesForType (Class
 Type, boolean includeNonSingletons, boolean allowEagerInit) {List
 
  
Result = new ArrayList
  
   
(); // Obtain the previously loaded class name String [] beanDefinitionNames = getBeanDefinitionNames (); for (String beanName: beanDefinitionNames) {// traverse all classes loaded before, find the classes registered to BeanFactoryPostProcessor and add them to the result, instantiate // 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 = (descridenonsingletons | 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 );}}}
  
 

Here, the registerBeanPostProcessors (beanFactory) instantiation process of refresh () is the same as that of invokeBeanFactoryPostProcessors.


Let's take a look at the initMessageSource () of refresh ()

// AbstractApplicationContextprotected void initMessageSource () {abstrablelistablebeanfactory beanFactory = getBeanFactory (); if (beanFactory. containsLocalBean (MESSAGE_SOURCE_BEAN_NAME) {// If the configuration file applicationContext. if messageSource is configured in xml, this is instantiated Based on the configuration file. messageSource = beanFactory. getBean (MESSAGE_SOURCE_BEAN_NAME, MessageSource. class); // Make MessageSource aware of parent MessageSource. if (this. pare Nt! = 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 CILS. 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 + "]") ;}}

Here is the configuration file applicationContext. messagesource is configured in xml, and is instantiated. If not, a DelegatingMessageSource is instantiated, and then set it to the container. When registering it to the singleton set


Then, the initApplicationEventMulticaster () of refresh () is to initialize ApplicationEventMulticaster. If we do not configure the custom ApplicationEventMulticaster, use SimpleApplicationEventMulticaster.



The idea of Instantiation is similar to that of instantiating messageSource, which takes precedence over the configuration file. If there is no clear configuration, use the default


Next, let's take a look at the registerListener () of refresh (), which registers the class that should be available at the original level of the static container, and then filters the listener from the class we previously loaded, the Shuai election instantiation process is the same as the previous invokeBeanFactoryPostProcessors () instantiation process. Remember to add the listener to the instantiated ApplicationEventMulticaster (which is actually a listener container ).

//AbstractApplicationContextprotected 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);}}

Next is the finispolicanfactoryinitialization () of refresh ()

// AbstractApplicationContext/*** Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */protected void finisincluanfactoryinitialization (abstrablelistablebeanfactory 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); // You Can cache all bean definition metadata beanFactory that will not be modified or further processed. freezeConfiguration (); // instantiate all the remaining Singleton beanbeanFactory. preInstantiateSingletons ();}


Next, the finishRefresh () of refresh ()


Finally, return to initWebApplicationContext in the previous blog.

//ClassLoaderpublic 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, etcif (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); set the container to the attribute of ServletContext. Previously, we used ServletContext as the attribute of WebApplicationContext. Therefore, the two can be associated through ServletContext. getAttribute (
WebApplicationContext. ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) to obtain the container


Since then, the Spring container has been created

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.