`

spring源码学习系列2.5-ApplicationContext初始化-设计模式

阅读更多
ApplicationContext容器的初始化可以通过模板方法设计模式概括


abstractApplicationContext#refresh是模板方法,定义了算法架构.其中
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// Initialize other special beans in specific context subclasses.
onRefresh();

由子类实现


abstractApplicationContext#refresh
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) {
				if (logger.isWarnEnabled()) {
					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;
			}
		}
	}


钩子方法(或由子类实现的方法)

第一个扩展点

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

由子类决定加载解析资源的方式

采用了委托模式将具体加载xml的工作委托给BeanDefinitionReader(即将xml解析到beanDefinitionMap)
XmlWebApplicationContext#loadBeanDefinitions
/**
	 * 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);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				reader.loadBeanDefinitions(configLocation);
			}
		}
	}



多个文件循环委托调用XmlBeanDefinitionReader


XmlBeanDefinitionReader中的工作处理xml->resource->inputstream->document对象.具体解析document对象通过委托模式委托给BeanDefinitionDocumentReader解析document对象
XmlBeanDefinitionReader#registerBeanDefinitions
@SuppressWarnings("deprecation")
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(getEnvironment());
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}



BeanDefinitionDocumentReader主要负责循环处理document节点.BeanDefinitionDocumentReader将具体解析不同元素到BeanDefinition的工作委托给BeanDefinitionParserDelegate
/**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}



第二个扩展点

// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

子类设置的post-processing,如Web环境,request,session等特性的设置

AbstractRefreshableWebApplicationContext#postProcessBeanFactory
/**
	 * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc.
	 */
	@Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
		beanFactory.ignoreDependencyInterface(ServletContextAware.class);
		beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

		WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
		WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
	}




第三个扩展点

// Initialize other special beans in specific context subclasses.
onRefresh();

子类需要实例化的其他特殊类,如web环境下,themeSource的设置

/**
	 * Initialize the theme capability.
	 */
	@Override
	protected void onRefresh() {
		this.themeSource = UiApplicationContextUtils.initThemeSource(this);
	}



具体方法

以获取bean为例,其中也使用了模板方法模式

abstractBeanFactory#doGetBean

// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								// Explicitly remove instance from singleton cache: It might have been put there
								// eagerly by the creation process, to allow for circular reference resolution.
								// Also remove any beans that received a temporary reference to the bean.
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
			throws BeanCreationException;



此处的模板方法模式是通过回调对象实现的




分享到:
评论

相关推荐

    Spring2.5-中文参考手册(这是个chm格式的文档)

    9. **模块化设计**:Spring 2.5的模块化设计使得开发者可以根据需要选择使用特定的模块,例如Web模块、AOP模块、数据访问模块等,保持项目的轻量级。 10. **注解驱动开发**:Spring 2.5大大增强了注解支持,使得...

    springframework2.5源代码

    以上这些知识点都是Spring Framework 2.5源代码中涉及的关键领域,通过深入研究源码,开发者不仅可以理解Spring的工作原理,还能学习到优秀的设计模式和编程实践。对于想要深入了解Spring框架的人来说,分析这些源...

    官方原版源码 spring-framework-5.2.9.RELEASE.zip

    1. **设计模式实践**:Spring源码中大量运用了工厂模式、单例模式、观察者模式等设计模式,学习源码能加深对设计模式的理解。 2. **性能优化**:通过对源码的学习,开发者可以了解Spring如何进行性能优化,如缓存、...

    spring源码-2022-08-14spring源码spring源码spring源码

    通过阅读源码,开发者不仅可以更好地理解和优化自己的应用,还可以学习到优秀的设计模式和最佳实践,提升自身的技术能力。同时,对于想要贡献于开源社区的开发者来说,理解Spring源码也是必不可少的一步。

    spring系列教程博客源码-东离与糖宝

    - 学习源码可以深入理解Spring的工作原理,例如Bean的生命周期、AOP的实现方式等。 - 通过"东离与糖宝"的博客源码,可能包含对上述概念的实战示例和解释,有助于实践和巩固理论知识。 这些内容只是Spring框架庞大...

    官方原版源码spring-framework-4.3.25.RELEASE.zip

    深入阅读源码,首先要理解设计模式和核心接口,如ApplicationContext、BeanFactory、AOP代理等。其次,通过跟踪代码执行流程,了解Spring如何初始化、加载配置、创建和管理Bean。最后,结合实际项目,实践源码中的...

    官方原版源码spring-framework-5.1.6.RELEASE.zip

    6. **文档与规范**:`spring-framework-5.1.6.RELEASE-docs.zip`包含完整的API文档和开发者指南,对于学习源码有着极大的辅助作用。而`spring-framework-5.1.6.RELEASE-schema.zip`则包含了Spring配置文件的XML ...

    官方原版源码spring-framework-5.1.3.RELEASE.zip

    这种设计模式降低了组件之间的耦合度,使得代码更易于测试和维护。 2. **面向切面编程(Aspect-Oriented Programming, AOP)**:Spring提供了AOP支持,允许开发者定义“切面”——一组关注点的模块化,这些关注点...

    spring2.5学习笔记

    ### Spring2.5 学习笔记关键知识点梳理 #### 搭建Spring的运行...以上是对Spring 2.5学习笔记的主要知识点进行了详细的总结和梳理。希望这些内容能够帮助读者更好地理解和掌握Spring 2.5框架的核心概念和技术细节。

    spring-framework-4-reference

    依赖注入是一种设计模式,用于实现控制反转,从而达到降低组件之间的耦合度的目的。依赖注入主要有三种方式:构造器注入、设值注入和接口注入。控制反转是依赖注入的一种实现方式,通过容器管理对象的创建和依赖关系...

    Spring的IoC容器初始化源码解析

    ### Spring的IoC容器初始化源码解析 #### 一、Spring框架的核心——IoC容器 Spring框架是一个开源的轻量级Java开发框架,其核心功能是IoC(Inversion of Control,控制反转)容器和AOP(Aspect Oriented ...

    Spring2.5学习笔记

    ### Spring2.5 学习笔记详解 #### 一、Spring 框架简介 Spring 是一个开源的轻量级 Java 开发框架,主要用于简化企业级应用的开发工作。Spring 提供了一系列强大的功能,比如控制反转 (Inversion of Control, IOC)...

    spring-framework-4.3.0源代码

    它初始化ApplicationContext并管理所有的MVC组件。 2. **Model-View-Controller(MVC)模式**:SpringMVC遵循这一经典设计模式,模型负责业务逻辑,视图负责展示结果,而控制器负责协调模型和视图。 3. **...

    官方原版源码spring-framework-5.2.0.RELEASE.zip

    对于开发者而言,深入研究Spring Framework 5.2.0的源码,可以了解到设计模式的应用,如工厂模式、单例模式、观察者模式等,以及AOP、依赖注入等核心概念的实现。此外,源码中还包含了大量的注释和文档,便于理解和...

    官方原版源码spring-framework-5.0.12.RELEASE.zip

    1. Bean工厂(BeanFactory)与ApplicationContext:BeanFactory是Spring的核心,负责创建、初始化、配置和管理Bean。ApplicationContext在此基础上增加了对国际化、事件发布、资源加载等功能。 2. 依赖注入(DI):...

    官方源码 spring-framework-5.3.7.zip

    通过对Spring Framework 5.3.7的官方源码学习,开发者不仅能掌握框架的运行机制,还能了解到设计模式和最佳实践,从而在实际项目中发挥出Spring的强大威力。无论是新手还是资深开发者,深入源码都是提升技能的有效...

    官方原版源码spring-framework-5.1.1.RELEASE.zip

    本文将围绕Spring Framework的核心特性、设计模式以及源码中的关键组件进行详尽的探讨。 一、核心特性 1. **依赖注入(Dependency Injection,DI)**:Spring框架的基础,通过XML配置或注解方式实现对象间的依赖...

    spring源码注释中文

    它通过默认配置简化了项目的初始化,并且内置了 Tomcat 或 Jetty 服务器,使得开发和部署更简单。 阅读 Spring 源码注释,可以深入理解以下知识点: - **依赖注入**:如何通过 XML 配置或注解实现对象之间的依赖...

    spring源码中英文注释

    通过深入研究这些源码和注释,开发者不仅可以提升自己的Spring框架技能,还能对Java编程有更深入的理解,尤其是在设计模式和面向接口编程方面。同时,这也有助于开发者在遇到问题时能够更快定位并解决。

Global site tag (gtag.js) - Google Analytics