Spring源码解读——Spring容器初始化 2

来源:互联网 发布:数据库%号 编辑:程序博客网 时间:2024/05/18 14:46

这篇博客是前一篇博客Spring源码解读——Spring容器初始化 1的延续,在看这篇博客之前,最后先看一下前一篇


接着我们继续看WebApplicationContext的refresh()方法

先看一下他的顺序图





//AbstractApplicationContext XmlWebApplicationContext的父类@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 准备容器的更新prepareRefresh();// 告诉子类刷新内部bean工厂ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 配置factory的标准容器特征,包括classloader和postprocessor等prepareBeanFactory(beanFactory);try {// 修改应用程序上下文的内部bean工厂标准后初始化。所有bean定义将被加载,但没有实例化bean。这允许在某些ApplicationContext实现类注册特殊BeanPostProcessorspostProcessBeanFactory(beanFactory);// 实例化所有注册到BeanFactoryPostProcessor的bean,如果有次序,就按照次序实例化,必须在单例实例化之前invokeBeanFactoryPostProcessors(beanFactory);// 实例化并调用所有注册BeanPostProcessor的bean,如果有次序,就按照次序实例化。 必须在 application bean的实例化之前调用。registerBeanPostProcessors(beanFactory);// 实例化MessageSource()initMessageSource();// 实例化ApplicationEventMulticasterinitApplicationEventMulticaster();// 实例化容器中特殊的类onRefresh();// 注册实现ApplicationListener的listenerregisterListeners();// 完成容器的beanFactory的实例化,初始化所有剩余单例beanfinishBeanFactoryInitialization(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()

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

这里都是为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,并加载类,实例化为对应的BeanDefinitionConfigurableListableBeanFactory 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. */@Overrideprotected final void refreshBeanFactory() throws BeansException {if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {DefaultListableBeanFactory beanFactory = createBeanFactory();  //这里创建了一个DefaultListableBeanFactory,供后面实例化beanbeanFactory.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 */@Overrideprotected 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)

//AbstractBeanDefinitionReaderpublic 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的那些类


//DefaultListableBeanFactoryprivate String[] doGetBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {List<String> result = new ArrayList<String>();// 获得之前加载的类名String[] beanDefinitionNames = getBeanDefinitionNames();    for (String beanName : beanDefinitionNames) {//遍历之前加载的全部类,并从中找出注册到BeanFactoryPostProcessor的那些类,把他们加入到result,为下面实例化// 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()

//AbstractApplicationContextprotected 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容器)中

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

接着就是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();// 实例化所有剩下的单例beanbeanFactory.preInstantiateSingletons();}


再接着,refresh()的finishRefresh()


最后回到上篇博客中的initWebApplicationContext中

//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); 将容器设置为ServletContext的属性,之前我们已经这是了ServletContext作为WebApplicationContext的属性,于是,两者相关联,可以通过ServletContext.getAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)获得容器


自此,Spring容器创建完毕

0 0