Spring ioc源码解析这一系列文章会比较枯燥,但是只要坚持下去,总会有收获,一回生二回熟,没有第一次,哪有下一次...

本系列目录:

Spring IOC(一)概览

Spring IOC(二)容器初始化

Spring IOC(三)依赖注入

Spring IOC(四)总结

一、Spring IOC概述

1.1 IOC

Ioc—Inversion of Control,即“控制反转”,是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

  ●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

  ●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

  用图例说明一下,传统程序设计都是主动去创建相关对象然后再组合起来,如下图:

当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如下图:

1.2 DI

DI—Dependency Injection,即“依赖注入”组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

  理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  ●谁依赖于谁:当然是应用程序依赖于IoC容器

  ●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源

  ●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象

  ●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

1.3 IOC和DI关系

  IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。

二、核心类源码解读

2.1 Spring IOC容器接口设计

Spring框架中,一旦把一个bean纳入到Spring IoC容器之中,这个bean的生命周期就会交由容器进行管理,一般担当管理者角色的是BeanFactory或ApplicationContext。下面来看一下IOC容器接口设计,如下图(默认JDK8):

如上图,可见主要有两条主线

  1.基本容器:BeanFactory-》HierarchicalBeanFactory-》ConfigurableBeanFactory

  • BeanFactory接口定义了基本的Ioc容器的规范,包括getBean()这样的Ioc容器的基本方法(通过这个方法可以从容器中取得Bean)。
  • HierarchicalBeanFactory增加了getParentBeanFactory()的接口功能,使BeanFactory具备了双亲Ioc容器的管理功能。
  • ConfigurableBeanFactory定义了一些配置功能,比如通过setParentBeanFactory()设置双亲Ioc容器,通过addBeanPostProcessor()配置Bean后置处理器,等等。

  2.高级容器:BeanFactory-》ListableBeanFactory-》ApplicationContext-》WebApplicationContext/ConfigurableApplicationContext

  • ListableBeanFactory细化了许多BeanFactory的接口功能,比如定义了getBeanDefinitionNames()接口方法;
  • ApplicationContext接口,它通过继承MessageSource、ResourcePatternResolver、ApplicationEventPublisher接口,在BeanFactory简单Ioc容器的基础上添加了许多对高级容器的特性支持。

2.2 BeanFactory接口

尊重源码,以下摘自BeanFactory源码注释翻译:

BeanFactory是获取spring bean容器的顶级接口。该接口被持有一系列bean definitions的对象所实现。依赖bean definitions,工厂返回一个原型实例或者一个单例实例。
通常,BeanFactory将加载存储在配置中的bean definitions资源(例如XML文档)。这些定义没有限制何种方式存储:LDAP, RDBMS, XML,properties file等。并且鼓励使用bean的依赖注入引用。

实现类需要支持Bean的完整生命周期,完整的初始化方法及其标准顺序(格式:接口 方法)为:

1.BeanNameAware setBeanName 设置bean名称
2.BeanClassLoaderAware setBeanClassLoader 设置bean类加载器
3.BeanFactoryAware setBeanFactory 设置bean工厂
4.EnvironmentAware setEnvironment 设置环境:profiles+properties
5.EmbeddedValueResolverAware setEmbeddedValueResolver 设置嵌入式值解析器
6.ResourceLoaderAware setResourceLoader 设置资源载入器,只适用于在应用程序上下文中运行
7.ApplicationEventPublisherAware setApplicationEventPublisher注入应用事件发布器ApplicationEventPublisher
8.MessageSourceAware setMessageSource 设置国际化支持
9.ApplicationContextAware setApplicationContext 设置应用上下文
10.ServletContextAware setServletContext 设置servlet上下文
11.BeanPostProcessors postProcessBeforeInitialization 执行bean处理器前置方法
12.InitializingBean afterPropertiesSet 执行初始化Bean设置完属性后置方法
13.a custom init-method definition 执行自定义初始化方法
14.BeanPostProcessors postProcessAfterInitialization 执行bean处理器后置方法

销毁顺序:
1.DestructionAwareBeanPostProcessors postProcessBeforeDestruction 销毁处理器的前置方法
2.DisposableBean destroy Bean销毁回调方法
3.a custom destroy-method definition 用户自定义销毁方法

关于Spring bean 生命周期的验证,飞机票:Spring bean 生命周期验证

下面来看一下BeanFactory接口源码:

 public interface BeanFactory {

     //转定义符
String FACTORY_BEAN_PREFIX = "&"; //定义5种获取Bean方法
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException; //判断容器是否含有指定名字的Bean
boolean containsBean(String name); //查询指定名字的Bean是否是Singleton类型的Bean.
boolean isSingleton(String name) throws NoSuchBeanDefinitionException; //查询指定名字的Bean是否是Prototype类型的
boolean isPrototype(String name) throws NoSuchBeanDefinitionException; //查询指定了名字的Bean的Class类型是否是特定的Class类型.
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; //查询指定名字的Bean的Class类型.
Class<?> getType(String name) throws NoSuchBeanDefinitionException; //查询指定了名字的Bean的所有别名,这些都是在BeanDefinition中定义的
String[] getAliases(String name); }

2.3 XmlBeanFactory实现类

spring3.1之后推荐直接使用:DefaultListableBeanFactory+XmlBeanDefinitionReader(第三节有样例)。虽然这个类已废弃,但不妨碍我们来简单理解一下

 @Deprecated
@SuppressWarnings({"serial", "all"})
public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
//载入资源构造
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
//通过载入资源和父类的BeanFactory构造
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
} }

1.在XmlBeanFactory中实例化了一个XmlBeanDefinitionReader,这个Reader对象就是用来处理以xml形式的持有类信息的BeanDefinitionl类。

2.BeanDefinitionl信息封装成Resource,作为构造入参

3.调用reader的loadBeanDefinitions,完成容器的初始化和注入。

2.4 模拟容器获取Bean

 public static void main(String[] args) {
//1.容器IOC获取bean初始化
ClassPathResource resource = new ClassPathResource("spring.xml");//载入资源
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);//构造reader
reader.loadBeanDefinitions(resource);//核心方法,解析bean定义
Dao dao = factory.getBean("daoImpl", Dao.class);//IOC容器DefaultListableBeanFactory通过名称和类class获取bean单例对象
dao.select();//执行Bean实例方法
}
spring.xml中就写一行:定义一个Bean即可
 <bean id="daoImpl" class="spring.aop.xml.dao.impl.DaoImpl" />

三、总结

本文概述IOC/DI 原理并分析了Spring核心接口设计,最后结合一个简单例子,模拟了最简单的容器DefaultListableBeanFactory从xml载入bean定义并生成bean对象的过程让大家有一个大体的认知。

下一章,我们将分析容器初始化。

=======================

参考

http://www.zzcode.cn/springioc/thread-39.html

谈谈对Spring IOC的理解

Spring IOC(一)概览的更多相关文章

  1. Spring IOC(二)容器初始化

    本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 一.ApplicationContext接 ...

  2. Spring IOC(三)依赖注入

    本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 1.AbstractBeanFactory ...

  3. Spring IOC(四)总结升华篇

    本系列目录 Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结升华 =============正文分割线===== ...

  4. Spring IoC总结

    Spring 复习 1.Spring IoC 1.1 基本概念 1.1.1 DIP(Dependency Inversion Principle) 字面意思依赖反转原则,即调用某个类的构造器创建对象时 ...

  5. 【初探Spring】------Spring IOC(三):初始化过程---Resource定位

    我们知道Spring的IoC起到了一个容器的作用,其中装得都是各种各样的Bean.同时在我们刚刚开始学习Spring的时候都是通过xml文件来定义Bean,Spring会某种方式加载这些xml文件,然 ...

  6. 【初探Spring】------Spring IOC(一)

    IOC:Inversion of Control(控制反转).IOC它所体现的并不是一种技术,而是一种思想,一种将设计好的对象交给容器来管理的思想.IOC的核心思想就体现在控制.反转这两个词上面,要理 ...

  7. spring ioc

    spring ioc是spring的核心之一,也是spring体系的基础,那么spring ioc所依赖的底层技术是什么的?反射,以前我们开发程序的时候对象之间的相互调用需要用new来实现,现在所有的 ...

  8. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  9. spring笔记6 spring IOC的中级知识

    1,spring ioc的整体流程,xml配置 spring ioc初始化的流程结合上图 步骤编号 完成的工作 1 spring容器读取配置文件,解析称注册表 2 根据注册表,找到相应的bean实现类 ...

随机推荐

  1. linux之ls、ll

    ls == list,根据不同的选项,列举指定目录或文件的相关信息,是Unix/Linux下最常用的命令之一,cd到某一目录下后执行的第一个命令. ls命令格式:ls [OPTION]... [FIL ...

  2. python Django rest-framework 序列化步骤

    django-rest-framework,是一套基于Django 的 REST 框架,是一个强大灵活的构建 Web API 的工具包.本文介绍一下 django-rest-framework 的简单 ...

  3. PCMU G.711U/PCMA G.711A简介

    PCMA(G.711A) 类型:Audio 制定者:ITU-T 所需频宽:64Kbps(90.4) 特性:PCMU和PCMA都能提供较好的语音质量,但是它们占用的带宽较高,需要64kbps. 优点:语 ...

  4. IPFS的配置安装

    目录 1. IPFS简介 2. IPFS本地环境安装 2.1 下载ipfs压缩包 2.2 安装 3. 项目配置 3.1 创建ipfs节点 3.2 修改节点默认存储空间 3.3 查看节点id 3.4 启 ...

  5. 安卓 dex 通用脱壳技术研究(四)

    /*     当第一个类执行到此函数时,我们在dvmDefineClass执行之前,也就是第一个类加载之前     注入我们的dump代码:即DumpClass()函数 */ static void  ...

  6. paddle实践

    Docker image阅读:https://github.com/PaddlePaddle/book/blob/develop/README.cn.md docker run -d -p 8888: ...

  7. 系统间通信——RPC架构设计

    架构设计:系统间通信(10)——RPC的基本概念 1.概述经过了详细的信息格式.网络IO模型的讲解,并且通过JAVA RMI的讲解进行了预热.从这篇文章开始我们将进入这个系列博文的另一个重点知识体系的 ...

  8. C++学习(八)(C语言部分)之 图形库

    有关图形库的学习笔记 1.安装 ww.easys.cn 2.创建win32控制台应用程序 .cpp文件(图形库必须创建cpp文件) *重点 3.安装好后 重启一下vs 图形库 是一些函数的集合 作用是 ...

  9. Iterator迭代器快捷键

    原文:https://blog.csdn.net/mingjie1212/article/details/51143444/ ★.iter 生成增强for:for (String s : locati ...

  10. Http&Tomcat

    一张图 tomcat的安装和启用: Tomcat有安装版和解压版(绿色版)安装版以.exe形式的安装包,双击安装到我们的电脑上,用的比较少.解压版,即绿色版,解压后直接使用,用的比较多 bin:脚本目 ...