原创内容,转载请注明出处
1、概述
ApplicationContext相对于BeanFactory增加的新特性:支持国际化(MessageSource)、访问资源(ResourceLoader)、应用事件(ApplicationEventPublisher)和一些附加服务(EnvironmentCapable)。
ApplicationContextd的主要实现子类有ClassPathXmlApplicationContext、FileSystemXmlApplicationContext 和XmlWebApplicationContext。下面我们以FileSystemXmlApplicationContext的实现作为分析。ClasspathXmlApplicationContext和FileSystemXmlApplicationContext的实现基本一致。
下图是FileSystemXmlApplicationContext类图
从类图中可以看出FileSystemXmlApplicationContext的直接父类是AbstractXmlApplicationContext,然而大部分ApplicationContext容器功能都已被FileSystemXmlApplicationContext的父类实现。FileSystemXmlApplicationContext类主要重写了父类DefaultResourceLoader的getResourceByPath(String path)方法,该方法作用是将xml文件转换成对应的Resource,FileSystemXmlApplicationContext在这里返回的是FileSystemResource,默认返回的是Classpath,故而ClassPathXmlApplicationContext不需要实现该方法。
2、编程式实现
创建bean.xml配置文件,内容如下
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="person" class="com.test.bean.Person"> <property name="name" value="ylxy"/> <property name="age" value="25"/> </bean> </beans>
创建Person类
package com.test.bean; public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void info(){ System.out.println("name:"+getName()+" age:"+getAge()); } }
创建junit测试代码
@Test public void test(){ ApplicationContext ctx = new FileSystemXmlApplicationContext("H:\\workspaceST\\cygoattest\\src\\test\\resources\\bean.xml"); Person p = (Person) ctx.getBean("person"); p.info(); }
执行测试结果如下
3、IOC初始化
跟踪FileSystemXmlBeanFactory类构造函数的代码上,可以看到IOC容器初始化是在AbstractApplicationContext类的refresh()方法中开始的,刷新IOC可分如下几个大步骤。
1.prepareRefresh()为初始化筹备环境,创建标准环境StandardEnviroment。
2.obtainFreshBeanFactory()刷新IOC容器,如果BeanFactory存在,则销毁,再创建DefaultListableBeanFactory容器。这里主要是BeanDefinition解析注册。
3.prepareBeanFactory()BeanFactory初始化,为BeanFactory添加初始化特性。
4.postProcessBeanFactory()为BeanFactory的BeanFactoryPostProcessor后置处理器,空方法空实现,需子类实现。
5.invokeBeanFactoryPostProcessors()调用BeanFactory的BeanFactoryPostProcessor后置处理器。
6.registerBeanPostProcessors()给BeanFactory注册BeanPostProcessor后置处理器。
7.initMessageSource()初始化消息源,即国际化。
8.initApplicationEventMulticaster()初始化应用事件多路广播实例。
9.onRefresh()初始化特殊Bean,未实现,给子类实现。
10.registerListeners()注册应用监听器。
11.finishBeanFactoryInitialization()结束BeanFactory的初始化,需要饥饿加载的单例Bean是在这里初始化加载缓存的。
12.finishRefresh()完成IOC初始化,并发布对应的事件(ContextRefreshedEvent)。
3.1、ObtainFreshBeanFactory()刷新IOC容器
进入该方法,该方法调用AbstraRefreshableBeanFactory类的refreshBeanFactory()方法去刷新BeanFactory。首先会判断当前BeanFactory是否存在,存在则销毁BeanFactory,然后在创建一个默认的DefaultListableBeanFactory对象,之后给这个BeanFactory初始化,最后就是BeanFactory加载和注册BeanDefinition的过程loadBeanDefinitions(beanFactory)。跟踪该方法,发现最终依旧是通过XmlBeanDefinitionReader类去完成解析和注册BeanDefinition,和BeanFactory编程式处理一样,可参考BeanFactory篇的IOC初始化实现。
3.2、initApplicationEventMulticaster()初始化应用事件多路广播器
首先判断ApplicationEventMulticaster对象bean是否已经被BeanFactory容器实例化过,或者BeanDefinition是否存在。如果上述条件成立,则直接通过BeanFactory容器依赖注入获取ApplicationEventMulticaster对象bean;否则,直接创建一个默认的应用事件多路广播器SimpleApplicationEventMulticaster实例,并将对象缓存到一个Map集合(singletonObjects)中。
3.3、registerListeners()注册应用监听器
获取应用上下文静态指定的的应用监听器ApplicationListener,并将应用监听器注册到应用事件多路广播器ApplicationEventMulticaster实例中。
从BeanDefinition集合中去获取ApplicationListener的子类的名称,并将名称注册到应用事件多路广播器ApplicationEventMulticaster实例中。
4、依赖注入
从源码上可以看出FileSystemXmlBeanFactory在IOC初始化时创建了一个DefaultListableBeanFactory对象作为内部BeanFactory容器,也就是说之后的依赖注入获取Bean的方式和BeanFactory获取的方式一模一样,可参照BeanFactory篇的依赖注入实现。
源代码如附件
相关推荐
《Spring源码分析——BeanFactory》 在Java的IoC(Inversion of Control)和DI(Dependency Injection)领域,Spring框架扮演着至关重要的角色。BeanFactory是Spring的核心组件之一,它是容器的基石,负责管理应用...
### Spring 源码分析——设计模式篇 #### 一、引言 Spring框架作为Java企业级开发领域中不可或缺的一部分,其内部集成了多种设计模式,不仅有助于提高系统的可维护性和扩展性,还能够帮助开发者更好地理解和应用...
本压缩包“Spring源码解析”提供了对Spring框架核心组件——IOC(Inversion of Control,控制反转)、AOP(Aspect Oriented Programming,面向切面编程)以及Transaction(事务管理)的源码分析,帮助开发者更全面地...
### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...
在源码分析的过程中,读者会深入理解Spring的内部工作机制,例如如何解析配置、如何创建bean实例、如何实现AOP代理等。这将有助于开发者编写更高效、更健壮的代码,也能为参与Spring的扩展或定制打下坚实基础。 总...
在源码分析中,我们首先看到`prepareContext`方法被调用,这是`SpringApplication`类中的一个重要方法,它负责初始化`ApplicationContext`(应用上下文)并为后续的bean加载做准备。 `prepareContext`方法做了以下...
《Spring框架源码分析——基于UML图的解读》 在深入探讨Spring框架源码之前,我们首先要理解什么是UML(统一建模语言)。UML是一种标准的图形化建模语言,用于软件设计和系统分析,它通过图表来表示系统的结构、...
1. **配置错误**:确保`struts.xml`和`applicationContext.xml`中的配置正确无误。比如,可能在定义AOP通知(advises)或切点(pointcuts)时,使用了错误的表达式或者没有正确地指定目标方法。 2. **类加载问题**...
6. **Spring源码分析**:通过阅读源码,理解Spring框架的工作原理,增强对框架的深入理解。 接下来,我们转向MyBatis,这是一个轻量级的持久层框架,它提供了灵活的SQL映射机制,使得数据库操作变得简单。"MyBatis3...
在深入理解Spring框架的过程中,源码分析是不可或缺的一环。本文将对Spring的IOC(Inversion of Control,控制反转)容器的源码进行初步探讨,旨在帮助读者从整体上把握其设计理念和实现方式。 Spring的核心就是IOC...
总之,通过深入学习Spring源码,开发者不仅可以提升编程能力,还能掌握更多软件设计和架构方面的知识,对于职业发展大有裨益。在实际开发中,结合源码理解,能够更好地解决遇到的问题,优化代码,提高工作效率。
在本资源中,我们提供了可以直接导入Eclipse的Spring源码的第五部分,版本为4.3.18。这一版本的Spring包含了众多改进和修复,对于理解Spring的工作原理以及进行自定义开发非常有帮助。 首先,让我们深入了解一下...
### Java毕业设计&课设——Spring源码深度解析+注解开发全套视频教程知识点概览 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一款开源轻量级Java EE应用框架,旨在简化企业级应用的开发过程。Spring...
Spring框架是Java开发中最常用的...对于初学者,通过阅读和分析这些源码,可以加深对Spring的理解,提升开发技能。同时,文档则可能包含Spring的使用指南、最佳实践以及常见问题解答,是学习和解决问题的重要参考资料。
实践是检验真理的唯一标准,通过分析和运行源码,你将能更好地掌握Spring框架的精髓。 总之,这份资料对于Spring初学者或希望深入理解Spring的开发者来说是一份宝贵的资源。通过系统学习并结合实践,你将能够熟练地...
5. **源码分析**: 在提供的源码第五部分中,我们可以看到具体实现这些整合的细节。例如,Action类如何被Spring初始化,以及如何通过Spring的代理调用DAO方法进行数据操作。同时,可能会包含Struts的配置文件...
在本系列的第一篇中,我们将深入探讨Spring框架的核心特性——依赖注入...手写DI源码不仅有助于提高对Spring源码的理解,也有助于提升我们对软件设计原则和模式的认识,这对于成为一名优秀的Java开发者至关重要。
**JSP源码——s2shDemo.zip** 是一个基于Java Web开发的项目,主要使用了Struts2、Spring和Hibernate这三大框架,通常被称为"S2SH"框架。这个项目提供了一个示例应用,帮助开发者理解和学习如何在实际开发中整合这三...