- 浏览: 50845 次
- 性别:
- 来自: 南京
文章分类
最新评论
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
钩子方法(或由子类实现的方法)
第一个扩展点
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
由子类决定加载解析资源的方式
采用了委托模式将具体加载xml的工作委托给BeanDefinitionReader(即将xml解析到beanDefinitionMap)
XmlWebApplicationContext#loadBeanDefinitions
多个文件循环委托调用XmlBeanDefinitionReader
XmlBeanDefinitionReader中的工作处理xml->resource->inputstream->document对象.具体解析document对象通过委托模式委托给BeanDefinitionDocumentReader解析document对象
XmlBeanDefinitionReader#registerBeanDefinitions
BeanDefinitionDocumentReader主要负责循环处理document节点.BeanDefinitionDocumentReader将具体解析不同元素到BeanDefinition的工作委托给BeanDefinitionParserDelegate
第二个扩展点
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
子类设置的post-processing,如Web环境,request,session等特性的设置
AbstractRefreshableWebApplicationContext#postProcessBeanFactory
第三个扩展点
// Initialize other special beans in specific context subclasses.
onRefresh();
子类需要实例化的其他特殊类,如web环境下,themeSource的设置
具体方法
以获取bean为例,其中也使用了模板方法模式
abstractBeanFactory#doGetBean
此处的模板方法模式是通过回调对象实现的
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;
此处的模板方法模式是通过回调对象实现的
发表评论
-
spring疑难解惑-循环依赖的解决
2020-06-17 23:27 554AbstractAutowireCapableBeanFact ... -
spring容器
2019-07-14 08:47 308private final ServletContainer ... -
spring容器
2019-07-13 23:35 0spring容器与springmvc容器 73 ... -
spring源码学习系列2.6-spring ioc原理-codes
2019-03-05 22:56 491web.xml <listener> < ... -
spring源码学习系列3.4-spring mvc原理-codes
2019-01-21 22:46 302本篇章从核心类角度解读springmvc的原理 web.xm ... -
spring源码学习系列4.2-spring aop原理-codes
2018-12-04 22:29 566jdk: Proxy InvocationHandler ... -
spring源码学习系列4.1-spring实现对ibatis的事务管理
2018-09-17 15:44 585事务由spring管理,可以理解为由spring管理数据库连接 ... -
spring源码学习系列4-3种常用的自动代理创建器
2018-09-02 15:48 5773种自动代理器是 AnnotationAwareAspectJ ... -
spring源码学习系列1.2-spring事务代理深入分析2
2018-05-27 19:46 457提示: BeanPostProcessor AopUtils ... -
spring源码学习系列3.3-DispatcherServlet初始化-设计模式
2018-05-07 11:12 630springmvc的核心是DispatcherServlet ... -
封装spring-security
2018-01-23 19:33 523github地址: https://github.com/ne ... -
eclipse导入spring源码
2018-05-12 07:20 986spring在git上的项目时gradle管理jar包的,所以 ... -
spring源码学习系列3.2.3-异常页面拦截机制
2017-07-29 19:07 777前序:本文的意义在于了解 tomcat处理异常 请求访问 ... -
spring源码学习系列3.2.2-How to bind String to Date
2017-07-17 12:40 604springmvc开发中,经常需将界面日期数据(String) ... -
spring源码学习系列3.2.1-command对象的绑定
2017-05-28 12:00 994在<spring源码学习系列3.2-handlerAda ... -
spring源码学习系列3.2-handlerAdapter执行
2017-05-28 12:01 414DispatcherServlet#doDispatch中调用 ... -
spring源码学习系列3.1-handlerMapping初始化
2017-05-28 11:56 706SimpleUrlHandlerMapping的继承体系 or ... -
spring源码学习系列2.4-finishRefresh会做什么
2017-05-06 16:36 584spring容器初始化完成后,调用finishRresh 该 ... -
spring源码学习系列3-springmvc原理
2017-05-28 11:56 461问题: springmvc是如何控 ... -
spring源码学习系列2-容器初始化入口-refresh
2017-04-23 21:33 480context=XmlWebApplicationContex ...
相关推荐
9. **模块化设计**:Spring 2.5的模块化设计使得开发者可以根据需要选择使用特定的模块,例如Web模块、AOP模块、数据访问模块等,保持项目的轻量级。 10. **注解驱动开发**:Spring 2.5大大增强了注解支持,使得...
以上这些知识点都是Spring Framework 2.5源代码中涉及的关键领域,通过深入研究源码,开发者不仅可以理解Spring的工作原理,还能学习到优秀的设计模式和编程实践。对于想要深入了解Spring框架的人来说,分析这些源...
1. **设计模式实践**:Spring源码中大量运用了工厂模式、单例模式、观察者模式等设计模式,学习源码能加深对设计模式的理解。 2. **性能优化**:通过对源码的学习,开发者可以了解Spring如何进行性能优化,如缓存、...
通过阅读源码,开发者不仅可以更好地理解和优化自己的应用,还可以学习到优秀的设计模式和最佳实践,提升自身的技术能力。同时,对于想要贡献于开源社区的开发者来说,理解Spring源码也是必不可少的一步。
- 学习源码可以深入理解Spring的工作原理,例如Bean的生命周期、AOP的实现方式等。 - 通过"东离与糖宝"的博客源码,可能包含对上述概念的实战示例和解释,有助于实践和巩固理论知识。 这些内容只是Spring框架庞大...
深入阅读源码,首先要理解设计模式和核心接口,如ApplicationContext、BeanFactory、AOP代理等。其次,通过跟踪代码执行流程,了解Spring如何初始化、加载配置、创建和管理Bean。最后,结合实际项目,实践源码中的...
6. **文档与规范**:`spring-framework-5.1.6.RELEASE-docs.zip`包含完整的API文档和开发者指南,对于学习源码有着极大的辅助作用。而`spring-framework-5.1.6.RELEASE-schema.zip`则包含了Spring配置文件的XML ...
这种设计模式降低了组件之间的耦合度,使得代码更易于测试和维护。 2. **面向切面编程(Aspect-Oriented Programming, AOP)**:Spring提供了AOP支持,允许开发者定义“切面”——一组关注点的模块化,这些关注点...
### Spring2.5 学习笔记关键知识点梳理 #### 搭建Spring的运行...以上是对Spring 2.5学习笔记的主要知识点进行了详细的总结和梳理。希望这些内容能够帮助读者更好地理解和掌握Spring 2.5框架的核心概念和技术细节。
依赖注入是一种设计模式,用于实现控制反转,从而达到降低组件之间的耦合度的目的。依赖注入主要有三种方式:构造器注入、设值注入和接口注入。控制反转是依赖注入的一种实现方式,通过容器管理对象的创建和依赖关系...
### Spring的IoC容器初始化源码解析 #### 一、Spring框架的核心——IoC容器 Spring框架是一个开源的轻量级Java开发框架,其核心功能是IoC(Inversion of Control,控制反转)容器和AOP(Aspect Oriented ...
### Spring2.5 学习笔记详解 #### 一、Spring 框架简介 Spring 是一个开源的轻量级 Java 开发框架,主要用于简化企业级应用的开发工作。Spring 提供了一系列强大的功能,比如控制反转 (Inversion of Control, IOC)...
它初始化ApplicationContext并管理所有的MVC组件。 2. **Model-View-Controller(MVC)模式**:SpringMVC遵循这一经典设计模式,模型负责业务逻辑,视图负责展示结果,而控制器负责协调模型和视图。 3. **...
对于开发者而言,深入研究Spring Framework 5.2.0的源码,可以了解到设计模式的应用,如工厂模式、单例模式、观察者模式等,以及AOP、依赖注入等核心概念的实现。此外,源码中还包含了大量的注释和文档,便于理解和...
1. Bean工厂(BeanFactory)与ApplicationContext:BeanFactory是Spring的核心,负责创建、初始化、配置和管理Bean。ApplicationContext在此基础上增加了对国际化、事件发布、资源加载等功能。 2. 依赖注入(DI):...
通过对Spring Framework 5.3.7的官方源码学习,开发者不仅能掌握框架的运行机制,还能了解到设计模式和最佳实践,从而在实际项目中发挥出Spring的强大威力。无论是新手还是资深开发者,深入源码都是提升技能的有效...
本文将围绕Spring Framework的核心特性、设计模式以及源码中的关键组件进行详尽的探讨。 一、核心特性 1. **依赖注入(Dependency Injection,DI)**:Spring框架的基础,通过XML配置或注解方式实现对象间的依赖...
它通过默认配置简化了项目的初始化,并且内置了 Tomcat 或 Jetty 服务器,使得开发和部署更简单。 阅读 Spring 源码注释,可以深入理解以下知识点: - **依赖注入**:如何通过 XML 配置或注解实现对象之间的依赖...
通过深入研究这些源码和注释,开发者不仅可以提升自己的Spring框架技能,还能对Java编程有更深入的理解,尤其是在设计模式和面向接口编程方面。同时,这也有助于开发者在遇到问题时能够更快定位并解决。