- 浏览: 1570372 次
文章分类
- 全部博客 (557)
- Spring 3 系列 (26)
- Spring 3 (4)
- oracle (7)
- java (6)
- css3 (1)
- andorid (11)
- IE中页面不居中 (1)
- crm (1)
- ibatis (1)
- jdbc (1)
- javacore (1)
- IT 生活 (3)
- 创业的简单感受 (1)
- web前端 (1)
- Java静态代理 (1)
- pdf (6)
- 模拟 (1)
- 数论 (1)
- ACM_POJ (2)
- C/C++求职面试必备考点 (1)
- 学习Android遇到的错误 (1)
- 嵌入式学习 (1)
- magento付费模板! (1)
- PHP (1)
- Oracle 开发 (1)
- MSSQL (1)
- javascript (6)
- 随感随想 (1)
- RobotFramework (1)
- Ajax (2)
- 数据库复习 (1)
- Java Web (1)
- Way (1)
- eclipse (1)
- 分布式 (1)
- 【ASP.NET开发】 (1)
- 搜索 (1)
- UML建模 (1)
- ANDROID (2)
- 编程技巧 (1)
- 程序员 (2)
- C语言相关 (1)
- Struts2 (1)
- 精品下载资源推荐 (1)
- CUDA (1)
- MFC (1)
- 游戏编程 (1)
- oracle数据库 (1)
- 暴力求解--哈希表 (1)
- 个人文章 (1)
- 最小生成树 (1)
- linux 基础 (1)
- Flex (1)
- Linux (1)
- UML (1)
- 云计算 (1)
- android ListView (1)
- java数据库连接池 (1)
- cxf (1)
- javas (0)
- jquery (2)
最新评论
-
lj杰:
您好,最近项目涉及这这方面的技术,能分享下源码不,小弟非常感谢 ...
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能 -
成大大的:
Android自动化测试从入门到精通网盘地址:https:// ...
4种手机自动化测试框架介绍 -
u012944589:
[size=xx-large][size=xx-small][ ...
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能 -
stone520520:
同求源码,这几天正想研究一下视频的相关功能mail: 1862 ...
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能 -
zhen8023wan:
源代码可以发给我一份吗?谢谢!qq邮箱:1796482787@ ...
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能
(转)菜鸟分析Spring源代码之 IOC容器的启动
20111225 By Tony
1. 前言
6月份开始,我就打算做一个Android下的快速开发架构。详见以下文章:
http://blog.csdn.net/nanjingjiangbiao/article/details/6557150
其中,我曾设想引入Spring来做整体的基础架构。后来发展到,我想研究研究Spring的底层代码。
只可惜项目太忙,只好先花钱买了本计先生的《Spring技术内幕》一书.
好书啊,好书啊,只可惜我看得头晕晕。从头到尾到处是代码,中文理解写的高深莫测,只可惜一个UML图都没有,真是天书啊天书。
怎么办呢?上网看评论,都说看不懂这本书的人都不是好程序员。
没办法,只好自我分析,自我批判Spring源代码。
2. 从Spring的最简单的Sample说起
上网到处都能抄到,以下这种小sample
- package com.hyron.tony;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.xml.XmlBeanFactory;
- import org.springframework.core.io.ClassPathResource;
- public class Test {
- public static void main(String[] args)throws Exception {
- BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
- GreetingService greetingService = (GreetingService)factory.getBean("greetingService");
- greetingService.sayGreeting();
- }
- }
以上最起码有两个东西我想搞清,
第一, XML文件的解析规则和算法在那里
第二, Object的动态生成在哪里
1. 分析
先上sample的时序图
首先,简单的紧,applicationContext.xml被构造成ClassPathResource对象,代码如下
- public ClassPathResource(String path, ClassLoader classLoader) {
- Assert.notNull(path, "Path must not be null");
- String pathToUse = StringUtils.cleanPath(path);
- if (pathToUse.startsWith("/")) {
- pathToUse = pathToUse.substring(1);
- }
- this.path = pathToUse;
- this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
- }
上面完成两个事情,第一是对文件path的编排。第二是,生成一个classloader出来,具体如下:
- public static ClassLoader getDefaultClassLoader() {
- ClassLoader cl = null;
- try {
- cl = Thread.currentThread().getContextClassLoader();
- }
- catch (Throwable ex) {
- // Cannot access thread context ClassLoader - falling back to system class loader...
- }
- if (cl == null) {
- // No thread context class loader -> use class loader of this class.
- cl = ClassUtils.class.getClassLoader();
- }
- return cl;
- }
但是,但是。。。。每一个Resource对象都有一个类加载器的变量??
接下来,资源的加载,也就是XML文件的解析,我们在XmlBeanFactory中看到如下代码:
- private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
- public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
- super(parentBeanFactory);
- this.reader.loadBeanDefinitions(resource);
- }
委托啊,委托啊,有木有啊有木有。。
XmlBeanFactory聚合了一个XmlBeanDefinitionReader来处理解析的事情。
然后,我们去XmlBeanDefinitionReader看看XML的解析
代码片段:
- //一个HashSet的ThreadLocal变量,用来保证在多线程情况下的数据安全
- //每一个进来的Resource都会被包装进去
- Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
然后,开始读XML文件咯
代码片段:
- //读stream
- InputStream inputStream = encodedResource.getResource().getInputStream();
- //inputstream被包装成JDK的document
- Document doc = this.documentLoader.loadDocument(
- inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
- //拿到document的根元素,开始登记
- Element root = doc.getDocumentElement();
- doRegisterBeanDefinitions(root);
下面就所谓的document的登记,这块的代码还是比较有水平的。
代码片段:
- //循环Dom树,开始解析
- 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);
- }
- }
- }
- //分别为import,alias,bean,beans四种元素做解析
- private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
- if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
- importBeanDefinitionResource(ele);
- }
- else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
- processAliasRegistration(ele);
- }
- else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
- processBeanDefinition(ele, delegate);
- }
- else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
- // recurse
- doRegisterBeanDefinitions(ele);
- }
- }
- //已bean元素为例,真正的解析代码如下
- //将DOM节点的属性都塞入AbstractBeanDefinition对象中
- public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
- BeanDefinition containingBean, AbstractBeanDefinition bd) {
- if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
- // Spring 2.x "scope" attribute
- bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
- if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
- error("Specify either 'scope' or 'singleton', not both", ele);
- }
- }
- else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
- // Spring 1.x "singleton" attribute
- bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ?
- BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
- }
- else if (containingBean != null) {
- // Take default from containing bean in case of an inner bean definition.
- bd.setScope(containingBean.getScope());
- }
- if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
- bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
- }
- String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
- if (DEFAULT_VALUE.equals(lazyInit)) {
- lazyInit = this.defaults.getLazyInit();
- }
- bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
- String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
- bd.setAutowireMode(getAutowireMode(autowire));
- String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
- bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
- if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
- String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
- bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
- }
- String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
- if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
- String candidatePattern = this.defaults.getAutowireCandidates();
- if (candidatePattern != null) {
- String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
- bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
- }
- }
- else {
- bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
- }
- if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
- bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
- }
- if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
- String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
- if (!"".equals(initMethodName)) {
- bd.setInitMethodName(initMethodName);
- }
- }
- else {
- if (this.defaults.getInitMethod() != null) {
- bd.setInitMethodName(this.defaults.getInitMethod());
- bd.setEnforceInitMethod(false);
- }
- }
- if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
- String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
- if (!"".equals(destroyMethodName)) {
- bd.setDestroyMethodName(destroyMethodName);
- }
- }
- else {
- if (this.defaults.getDestroyMethod() != null) {
- bd.setDestroyMethodName(this.defaults.getDestroyMethod());
- bd.setEnforceDestroyMethod(false);
- }
- }
- if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
- bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
- }
- if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
- bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
- }
- return bd;
- }
- //最后,在bean容器中注册BeanDefiniton
- //这里所谓的bean容器就是XmlBeanFactory在构造的时候,塞入的DefaultListableBeanFactory
- //其中,储存用的数据结构是个线程安全的ConcurrentHashMap
- synchronized (this.beanDefinitionMap) {
- Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
- if (oldBeanDefinition != null) {
- if (!this.allowBeanDefinitionOverriding) {
- throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
- "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
- "': There is already [" + oldBeanDefinition + "] bound.");
- }
- else {
- if (this.logger.isInfoEnabled()) {
- this.logger.info("Overriding bean definition for bean '" + beanName +
- "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
- }
- }
- }
- else {
- this.beanDefinitionNames.add(beanName);
- this.frozenBeanDefinitionNames = null;
- }
- this.beanDefinitionMap.put(beanName, beanDefinition);
- resetBeanDefinition(beanName);
- }
。。。至于Bean的生成,下次再说吧,累了,去吃饭去了。。。
Bean的生成,中间有关于单例,线程安全,性能,缓存,都会是比较有意思的问题。
发表评论
-
Spring Batch学习(一)介绍
2015-01-08 17:17 8458为什么我们需要批处理? 我们不会总是想要立即得到需要的信 ... -
spring包详解
2012-04-22 14:58 1726下载的spring包中文件及各种包众多,在项目中往往只有 ... -
我的spring学习笔记2-IoC(反向控制 依赖注入)
2012-04-10 07:50 2782IoC(反向控制 依赖注入)这是Spring提出来了,这也是S ... -
我的spring学习笔记1-spring 简介
2012-04-10 07:49 21881.1. 概览 ... -
我的spring学习笔记15-容器扩展点之PropertyOverrideConfigurer
2012-04-22 14:55 1905PropertyOverrideConfigurer类似于Pr ... -
我的spring学习笔记14-容器扩展点之PropertyPlaceholderConfigurer
2012-04-22 14:55 1875PropertyPlaceholderConfigurer是个 ... -
我的spring学习笔记10-轻量级_Spring框架
2012-04-14 21:59 2006一、问题提问: ... -
我的spring学习笔记9-Spring使用工厂方法实例化Bean的注意点
2012-04-14 21:59 1589方法一: <bean id="m ... -
我的spring学习笔记8-Spring中Bean的实例化
2012-04-14 21:59 1502在Spring中要实例化一个Bean有几种方法: 1、最常用 ... -
我的spring学习笔记7-Spring的Bean配置文件给Bean定义别名
2012-04-14 21:59 3047本文介绍如何给Spring的Bean配置文件的Bean定义别名 ... -
我的spring学习笔记6-ApplicationContext实例化的参数兼容思想
2012-04-14 21:59 1519ApplicationContext能读取多个Bean定义文件 ... -
我的spring学习笔记5-如何使用ApplicationContext替换BeanFactory
2012-04-12 22:03 1919如何使用ApplicationContext替换BeanFac ... -
我的spring学习笔记4-ApplicationContext详解
2012-04-12 22:03 4368ontext的核心作用是ApplicationConte ... -
我的spring学习笔记3-BeanFactory 详解
2012-04-12 22:03 19911、BeanFactory是 ... -
我的spring学习笔记2-IoC(反向控制 依赖注入)
2012-04-12 22:03 1237IoC(反向控制 依赖注入)这是Spring提出来了,这也是S ... -
我的spring学习笔记-spring 简介
2012-04-12 22:03 15991.1. 概览 ... -
Spring中事件处理de小技巧
2012-04-08 12:01 1624Spring 中提供一些Aware相关de接口,Be ... -
关于使用Spring导致c3p0数据库死锁问题
2012-04-08 11:59 6526这个问题我实在是为整个 springsource 的员工蒙羞 ... -
SPRING多数据源切换的问题和解决方法
2012-04-08 11:56 4522在应用中,需要热切换数据源。但发现如下问题: J ... -
再析在spring框架中解决多数据源的问题
2012-04-08 11:52 1764在前面我写了《如何在 spring 框架中解决 ...
相关推荐
在Spring源代码解析的第一部分,我们将聚焦于IOC容器,特别是BeanFactory接口,它是所有Spring容器的基础。 BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的...
Spring源代码解析(二):IoC容器在Web容器中的启动 Spring源代码解析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务...
当我们在Web环境中运行Spring应用时,IoC容器需要在Web容器(如Tomcat、Jetty等)中启动并运行。这个过程涉及到一系列的初始化步骤,确保Spring能够正确地与Web容器集成。 首先,`WebApplicationContext`是`...
Spring源代码解析2:IoC容器在Web容器中的启动.doc Spring源代码解析3:Spring JDBC .doc Spring源代码解析4:Spring MVC .doc Spring源代码解析5:Spring AOP获取Proxy .doc Spring源代码解析6:Spring声明式事务...
Spring源代码解析2:IoC容器在Web容器中的启动;Spring源代码解析3:Spring JDBC ; Spring源代码解析4:Spring MVC ;Spring源代码解析5:Spring AOP获取Proxy;Spring源代码解析6:Spring声明式事务处理 ; ...
本文将通过分析Spring源代码来揭示其IoC容器的工作原理。 首先,我们要理解IoC的概念。IoC是一种设计模式,它将对象的创建和管理从应用逻辑中解耦出来,由一个中心组件(如Spring的ApplicationContext)负责。在...
3. `TestIoC.java`:这是一个关于IoC容器的测试类,它可能使用Spring的ApplicationContext接口来加载bean.xml配置,然后通过容器获取并测试bean实例。 4. `ServiceBean.java`:这可能是一个通用的服务bean,用于...
2. **Web环境下的IOC容器启动**:"spring源代码解析(二):IOC容器在web中启动.doc"涵盖了在Web应用中初始化Spring容器的过程,包括ApplicationContext的创建、DispatcherServlet的配置以及如何在Web环境中注入bean...
从标签“源码”来看,这个项目可能提供了源代码,供学习者研究和分析。通过阅读源码,开发者可以深入了解IoC容器的工作原理,包括如何解析配置,如何实例化和管理Bean,以及如何处理依赖关系。这对于理解Spring框架...
### Spring IoC容器部署实现详解 #### 一、Spring IoC容器概述 Spring框架的核心特性之一就是Inversion of Control(IoC),也被称为Dependency Injection(DI)。IoC容器是Spring框架的重要组成部分,它负责管理...
源代码分析有助于深入理解Spring的工作原理,提升编程技能,并且能够帮助开发者在遇到问题时进行调试和优化。 1. **Spring IoC容器**: Spring的核心是IoC容器,它负责管理对象的生命周期和依赖关系。通过XML配置...
1. 源代码文件(.java):这些文件可能包含了实现IOC容器的类,如一个用于扫描注解并处理依赖注入的主容器类,以及带有注解的被注入对象类。 2. 注解(Annotations):例如`@Autowired`或自定义注解,用于标记需要...
IOC(Inversion of Control)容器是软件设计模式中的一种,它将对象的创建和管理权从代码本身转移到一个外部容器,即IOC容器。这种反转控制使得程序更加灵活,降低了组件之间的耦合性,提高了可测试性和可维护性。本...
### Spring IoC容器的核心概念与应用 #### 一、IoC基本定义 IoC(Inversion of Control,控制反转)是一种设计思想,在Spring框架中主要体现在这样一种方式:原本在程序代码中由开发者自己控制的对象的创建过程以及...
《精通Spring源代码》是罗时飞先生关于Spring框架深入解析的一部著作,旨在帮助开发者更深入地理解Spring的工作原理,提升对Java企业级应用开发的掌控能力。本压缩包包含的文件名为“精通Spring源码”,这通常是一个...
spring-context:上下文,即IOC容器 spring-context-support:对IOC的扩展,以及IOC子容器 spring-context-indexer:类管理组件和Classpath扫描 spring-expression:表达式语句 切面编程: spring-aop:面向切面编程,...
在实际开发中,`maventest05`这个文件可能是Spring项目的一个Maven模块,其中包含了项目源代码、配置文件和Maven构建文件。Maven是一个流行的项目管理和构建工具,它通过`pom.xml`文件管理项目的依赖,构建过程,...