`

请您先登录,才能继续操作

三、Spring源码分析——ApplicationContext

阅读更多

原创内容,转载请注明出处

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

    《Spring源码分析——BeanFactory》 在Java的IoC(Inversion of Control)和DI(Dependency Injection)领域,Spring框架扮演着至关重要的角色。BeanFactory是Spring的核心组件之一,它是容器的基石,负责管理应用...

    Spring 源码分析文档----自用

    ### Spring 源码分析——设计模式篇 #### 一、引言 Spring框架作为Java企业级开发领域中不可或缺的一部分,其内部集成了多种设计模式,不仅有助于提高系统的可维护性和扩展性,还能够帮助开发者更好地理解和应用...

    Spring源码解析.zip

    本压缩包“Spring源码解析”提供了对Spring框架核心组件——IOC(Inversion of Control,控制反转)、AOP(Aspect Oriented Programming,面向切面编程)以及Transaction(事务管理)的源码分析,帮助开发者更全面地...

    Spring源码分析_Spring_IOC

    ### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...

    spring 源码中文注释

    在源码分析的过程中,读者会深入理解Spring的内部工作机制,例如如何解析配置、如何创建bean实例、如何实现AOP代理等。这将有助于开发者编写更高效、更健壮的代码,也能为参与Spring的扩展或定制打下坚实基础。 总...

    SpringBoot源码解析——BeanDefinitionLoader 源码分析.docx

    在源码分析中,我们首先看到`prepareContext`方法被调用,这是`SpringApplication`类中的一个重要方法,它负责初始化`ApplicationContext`(应用上下文)并为后续的bean加载做准备。 `prepareContext`方法做了以下...

    spring源码UML图

    《Spring框架源码分析——基于UML图的解读》 在深入探讨Spring框架源码之前,我们首先要理解什么是UML(统一建模语言)。UML是一种标准的图形化建模语言,用于软件设计和系统分析,它通过图表来表示系统的结构、...

    struts2+spring集成bug——使用AOP时可能遇到的问题分析

    1. **配置错误**:确保`struts.xml`和`applicationContext.xml`中的配置正确无误。比如,可能在定义AOP通知(advises)或切点(pointcuts)时,使用了错误的表达式或者没有正确地指定目标方法。 2. **类加载问题**...

    spring源码解析和mybatis学习

    6. **Spring源码分析**:通过阅读源码,理解Spring框架的工作原理,增强对框架的深入理解。 接下来,我们转向MyBatis,这是一个轻量级的持久层框架,它提供了灵活的SQL映射机制,使得数据库操作变得简单。"MyBatis3...

    小读spring ioc源码(一)——整体介绍

    在深入理解Spring框架的过程中,源码分析是不可或缺的一环。本文将对Spring的IOC(Inversion of Control,控制反转)容器的源码进行初步探讨,旨在帮助读者从整体上把握其设计理念和实现方式。 Spring的核心就是IOC...

    spring源码, 可以很好的学习spring源码, 对spring更深入理解

    总之,通过深入学习Spring源码,开发者不仅可以提升编程能力,还能掌握更多软件设计和架构方面的知识,对于职业发展大有裨益。在实际开发中,结合源码理解,能够更好地解决遇到的问题,优化代码,提高工作效率。

    spring源码可导入eclipse版本 第五部分

    在本资源中,我们提供了可以直接导入Eclipse的Spring源码的第五部分,版本为4.3.18。这一版本的Spring包含了众多改进和修复,对于理解Spring的工作原理以及进行自定义开发非常有帮助。 首先,让我们深入了解一下...

    java毕业设计&课设-spring源码深度解析+注解开发全套视频教程(视频+源码).doc

    ### Java毕业设计&课设——Spring源码深度解析+注解开发全套视频教程知识点概览 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一款开源轻量级Java EE应用框架,旨在简化企业级应用的开发过程。Spring...

    Spring有关资料 源码

    Spring框架是Java开发中最常用的...对于初学者,通过阅读和分析这些源码,可以加深对Spring的理解,提升开发技能。同时,文档则可能包含Spring的使用指南、最佳实践以及常见问题解答,是学习和解决问题的重要参考资料。

    Spring学习笔记+学习源码.zip

    实践是检验真理的唯一标准,通过分析和运行源码,你将能更好地掌握Spring框架的精髓。 总之,这份资料对于Spring初学者或希望深入理解Spring的开发者来说是一份宝贵的资源。通过系统学习并结合实践,你将能够熟练地...

    轻量级J2EE企业应用实战——Struts+Spring+Hibernate整合开发 源码第五部分

    5. **源码分析**: 在提供的源码第五部分中,我们可以看到具体实现这些整合的细节。例如,Action类如何被Spring初始化,以及如何通过Spring的代理调用DAO方法进行数据操作。同时,可能会包含Struts的配置文件...

    【框架源码篇 01】Spring源码-手写IOC

    在本系列的第一篇中,我们将深入探讨Spring框架的核心特性——依赖注入...手写DI源码不仅有助于提高对Spring源码的理解,也有助于提升我们对软件设计原则和模式的认识,这对于成为一名优秀的Java开发者至关重要。

    JSP源码——s2shDemo.zip

    **JSP源码——s2shDemo.zip** 是一个基于Java Web开发的项目,主要使用了Struts2、Spring和Hibernate这三大框架,通常被称为"S2SH"框架。这个项目提供了一个示例应用,帮助开发者理解和学习如何在实际开发中整合这三...

Global site tag (gtag.js) - Google Analytics