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(二)容器初始化
本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 一.ApplicationContext接 ...
- Spring IOC(三)依赖注入
本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 1.AbstractBeanFactory ...
- Spring IOC(四)总结升华篇
本系列目录 Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结升华 =============正文分割线===== ...
- Spring IoC总结
Spring 复习 1.Spring IoC 1.1 基本概念 1.1.1 DIP(Dependency Inversion Principle) 字面意思依赖反转原则,即调用某个类的构造器创建对象时 ...
- 【初探Spring】------Spring IOC(三):初始化过程---Resource定位
我们知道Spring的IoC起到了一个容器的作用,其中装得都是各种各样的Bean.同时在我们刚刚开始学习Spring的时候都是通过xml文件来定义Bean,Spring会某种方式加载这些xml文件,然 ...
- 【初探Spring】------Spring IOC(一)
IOC:Inversion of Control(控制反转).IOC它所体现的并不是一种技术,而是一种思想,一种将设计好的对象交给容器来管理的思想.IOC的核心思想就体现在控制.反转这两个词上面,要理 ...
- spring ioc
spring ioc是spring的核心之一,也是spring体系的基础,那么spring ioc所依赖的底层技术是什么的?反射,以前我们开发程序的时候对象之间的相互调用需要用new来实现,现在所有的 ...
- Spring IoC源码解析——Bean的创建和初始化
Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...
- spring笔记6 spring IOC的中级知识
1,spring ioc的整体流程,xml配置 spring ioc初始化的流程结合上图 步骤编号 完成的工作 1 spring容器读取配置文件,解析称注册表 2 根据注册表,找到相应的bean实现类 ...
随机推荐
- linux之ls、ll
ls == list,根据不同的选项,列举指定目录或文件的相关信息,是Unix/Linux下最常用的命令之一,cd到某一目录下后执行的第一个命令. ls命令格式:ls [OPTION]... [FIL ...
- python Django rest-framework 序列化步骤
django-rest-framework,是一套基于Django 的 REST 框架,是一个强大灵活的构建 Web API 的工具包.本文介绍一下 django-rest-framework 的简单 ...
- PCMU G.711U/PCMA G.711A简介
PCMA(G.711A) 类型:Audio 制定者:ITU-T 所需频宽:64Kbps(90.4) 特性:PCMU和PCMA都能提供较好的语音质量,但是它们占用的带宽较高,需要64kbps. 优点:语 ...
- IPFS的配置安装
目录 1. IPFS简介 2. IPFS本地环境安装 2.1 下载ipfs压缩包 2.2 安装 3. 项目配置 3.1 创建ipfs节点 3.2 修改节点默认存储空间 3.3 查看节点id 3.4 启 ...
- 安卓 dex 通用脱壳技术研究(四)
/* 当第一个类执行到此函数时,我们在dvmDefineClass执行之前,也就是第一个类加载之前 注入我们的dump代码:即DumpClass()函数 */ static void ...
- paddle实践
Docker image阅读:https://github.com/PaddlePaddle/book/blob/develop/README.cn.md docker run -d -p 8888: ...
- 系统间通信——RPC架构设计
架构设计:系统间通信(10)——RPC的基本概念 1.概述经过了详细的信息格式.网络IO模型的讲解,并且通过JAVA RMI的讲解进行了预热.从这篇文章开始我们将进入这个系列博文的另一个重点知识体系的 ...
- C++学习(八)(C语言部分)之 图形库
有关图形库的学习笔记 1.安装 ww.easys.cn 2.创建win32控制台应用程序 .cpp文件(图形库必须创建cpp文件) *重点 3.安装好后 重启一下vs 图形库 是一些函数的集合 作用是 ...
- Iterator迭代器快捷键
原文:https://blog.csdn.net/mingjie1212/article/details/51143444/ ★.iter 生成增强for:for (String s : locati ...
- Http&Tomcat
一张图 tomcat的安装和启用: Tomcat有安装版和解压版(绿色版)安装版以.exe形式的安装包,双击安装到我们的电脑上,用的比较少.解压版,即绿色版,解压后直接使用,用的比较多 bin:脚本目 ...