spring的ioc之beanFactory

一、IOC 依赖注入

概念:这个概念要理解有一定的难度,我阐述一下我的理解:

它包括两个内容:

其一是控制

其二是反转

    那到底是什么东西的“控制”被“反转”了呢?我借鉴《Sring3.x 企业级开发》的例子:一部电影要拍摄要有导演、剧本、演员等,而剧本里的角色由哪些演员来扮演 ? 是谁控制呢?一般的思路是剧本里的角色被固定一个演员。“控制”是指选择一个角色扮演者的控制权,“反转”是指这种控制权从剧本中移除,转交到导演手中。这样剧本就活了,不会因为一个演员不干了,电影就不能拍了。

在软件中,即是某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定。可以灵活地去选择哪个具体实现的类,而不用修改调用类的代码。这就符合了开闭原则。

 

二、 Ioc的类型

1、 构造函数注入

Public class A{

Private B b;

Public A (B b){

This.b = b;

}

 

Public void hell(){

B.hell();

}

}

从上述代码可以看到在A 实例时通过构造函数对 B 进行实例化。

2、 属性注入

就是在调用类中要注入的类生成一个set 方法;在使用时通过调用这个方法来为该注入类注入对象。

3、 接口注入

将调用类所有依赖注入的方法抽取到一个借口中,调用类通过实现该借口提供的相应的注入方法。为了采取借口注入的方式,必须先声明一个借口。

 

 

三、 通过容器完成依赖关系的注入

提供一个容器来存储各个类的实例化和他们的关系,使他们完全解耦。Spring 就是这样做的,它帮住完成类的初始化与装配工作,让开发者从这些底层实现类的实例化、依赖关系装配等工作中脱离出来,专注于更有意义的业务逻辑开发工作, Spring 同过配置文件或注解描述类和类之间的依赖关系,自动完成类的初始化和依赖注入的工作。具体是如何来进行这些工作的呢?答案一定是 java 的反射机制。

 

 

 

 

下面我要看看spring 是如何实现 ioc

 

Spring通过一个配置文件来描述 Bean Bean 之间的依赖关系,利用 java 的反射功能实例化 Bean 并建立 Bean 之间的依赖关系。 Ioc 在完成基本的实例以为还提供了 Bean 实例的缓存、 Bean 生命周期管理、 Bean 的实例代理、事件发布、资源加载等功能。

对于Spring  的使用者而言, IOC  容器实际上是什么呢?我们可以说 BeanFactory 就是我们看到的 IoC  容器,当然了 Spring  为我们准备了许多种 IoC  容器来使用,这样可以方便我们从不同的层面,不同的资源位置,不同的形式的定义信息来建立我们需要的 IoC  容器。

 

BeanFactory

Spring中最最核心的一个借口就是 BeanFactory, 它可以说是 spring 的心脏。 Spring ioc 就是围绕着 BeanFactory 展开的。

这是 spring IoC容器相关的核心类图

上图简化了类之间的依赖关系,化繁为简,主要关于一下接口的继承体系。BeanFactory 接口定义了 spring 容器所能提供的最基本的服务。 同时, spring 又提供了几个其他的接口,作为对基本接口的扩展。 DefaultListableBeanFactory Spring 框架中最基本的 容器实现类,大多数的容器类都是在这个容器实现类的基础上进行功能的扩展。

     从接口的继承关系上来看,spring 遵守了单一职责原则,每一个接口只负责新增一个新的功能点,可以根据功能上的需要,选择不同的接口去实现。

 

BeanFactory 接口   spring ioc 容器核心接口 , 主要功能为根据 bean 的名称获取 bean bean 的信息,提供的接口功能有:

查找是否有指定名称的 bean, 根据名称获取 bean, 根据名称获取所有的别名,根据名称获取 bean class 类型,根据名称判断 bean 是否是单例或 prototype  判断名称为 name bean 是否与指定类型相匹配

n ListableBeanFactory 接口: 继承自 BeanFactory ,提供对容器内的 bean 的枚举与遍历功能,主要功能有:查找是否有指定名称 bean 的定义 获取容器内 bean 的数量及所有 bean 的名称 根据指定类型获取 bean 的集合

n HierarchicalBeanFactory 接口: 继承自 BeanFactory ,支持父子 BeanFactory 的继承,主要功能有判断当前 BeanFactory 中是否含有指定名称的 bean 、获取父 BeanFactory

n ConfigurableBeanFactory 接口: 继承自 HierarchicalBeanFactory SingletonBeanRegistry 接口,为beanFactory 添加了一些配置的功能,包括添加 BeanPostProcessor 后置处理器、 PropertyEditorRegistrar 属性编辑器、别名,设置父beanFactory 、类加载器缓存,并提供了对 Scope 的支持,除此之外还有销毁 bean 和容器中所有单例,获取后置处理器数量,类型转换器,复制 ConfigurableBeanFactory  信息,判断指定的bean 当前是否正在创建等功能。同时,由于该接口继承自 SingletonBeanRegistry 接口,因此其也具有管理 beanFactory 中的单例对象的功能。

n AutowireCapableBeanFactory 接口: 继承自 BeanFactory ,提供自动装配的功能

n ConfigurableListableBeanFactory 接口 继承自 ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory 此三个接口,并定义了获取 BeanDefinition 和预先实例化单例 bean 的功能。

n AbstractBeanFactory BeanFactory 接口进行了基础性的实现,提供了 ConfigurableBeanFactory 接口的所有功能。其功能和特点主要有:

通过继承自 DefaultSingletonBeanRegistry 类,提供了对单例对象的 cache 缓存可以根据 bean 名称,决定对象是 prototype 还是单例类型 Bean 别名的支持

Bean 定义 RootBeanDefinition ChildBeanDefinition 的合并 FactoryBean 创建 bean 与其本身的支持 Bean 析构时调用 destroy() 方法或其本身配置的销毁方法进行后置处理 实现了 HierarchicalBeanFactory 接口,支持 BeanFactory 容器的父子继承关系

本类给其子类留下了三个抽象方法:

boolean containsBeanDefinition(String beanName);

BeanDefinition getBeanDefinition(String beanName);

createBean(String beanName, RootBeanDefinition mbd, Object[] args);

 

 

 

 

 

 

ApplicationContext

如果说 BeanFactory spring 的心脏那么 ApplicationContext 就是 Spring 的躯体了。 ApplicationContext 是从 BeanFactory 扩展生成的。

ApplicationContext 接口:  spring context核心接口 , 其由 BeanFactory 接口的子接口扩展而来,因此具有 BeanFactory 的所有功能,又因为其继承了 MessageSource, ApplicationEventPublisher, ResourcePatternResolver 接口,因此又具有国际化消息解析,资源加载, ApplicationEvent 事件发布的功能。在此接口自己定义的方法中提供了获取父 ApplicationContext 、获取自动装配 bean 工厂,获取启动时间和显示名称这四项功能。

n ConfigurableApplicationContext 接口 继承自ApplicationContext Lifecycle 接口,为客户端提供了配置与定制 ApplicationContext 相关设置的功能,主要内容有:设置父 ApplicationContext 添加BeanFactory 后置处理器 BeanFactoryPostProcessor 添加ApplicationListener 获取ApplicationContext 内部的 BeanFactory(ConfigurableListableBeanFactory 类型 ) 刷新与关闭applicaionContext 注册关闭时的shutdown hook 判断当前applicationcontext 是否处于活动 (active 状态 )

n AbstractApplicationContext 类: ApplicationContext 进行抽象实现,其内部的 refresh() 方法实现了 ApplicationContext 的启动流程,其 doClose() 方法则实现了 applicationcontext 的关闭流程。另外对其继承的多个接口中的方法,均有默认实现。

此类给子类留下了三个抽象方法:

     ConfigurableListableBeanFactory getBeanFactory();

void closeBeanFactory();

void refreshBeanFactory();

n AbstractRefreshableApplicationContext 继承自 AbstractApplicationContext 类,支持多次刷新。此类对其基类 AbstractApplicationContext 所留下的三个方法均进行了默认实现,其中在 refreshBeanFactory() 方法中完成了刷新的功能,并调用了 createBeanFactory() 方法创建一个 DefaultListableBeanFactory 对象来作为代理的内部类,在其子类的实现中将通过此 beanFactory 来加载配置中的 BeanDefinition ,创建和管理 bean 。此类只留给子类一个抽象方法:

    void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)

beanFactory 中加载 beanDefinitions

n AbstractXmlApplicationContext 继承自AbstractRefreshableApplicationContext 类,其内部实现了从 xml 配置文件中加载和解析 beanDefinition

 

 

两者的区别:

1、 初始化,beanFactory 在初始化容器时,并未实例化 bean 直到第一次调用 getbean 时才会初始化该 bean ,而 applicationcontext 初始化时这在初始化应用上下文时就实例化所有单例的 bean

2、 Applicationcontext beanFactory 假如了一些更好使用的功能。而且 beanFactory 的许多功能需要通过编程实现而 Applicationcontext 可以通过配置实现。比如后处理 bean Applicationcontext 直接配置在配置文件即可而 beanFactory 这要在代码中显示的写出来才可以被容器识别。

3、 beanFactory主要是面对与 spring 框架的基础设施,面对 spring 自己。而 Applicationcontex 主要面对与 spring 使用的开发者。基本都会使用 Applicationcontex 并非 beanFactory

 

 

webApplicationcontext

主要是面对与web 开发使用的。是通过 Applicationcontext扩展而来的。它允许从 web 根目录的路径加载配置文件,而且还和 web 环境有一定的融合,比如 servletcontext 的相融合。

 

Servletcontext中有 webApplicationcontext 的引用。在 webApplicationcontex 中也可以得到 Servletcontext 。如上图所示。

而且webApplicationcontext 可以随 web 容器的启动而启动 spring ioc 容器。主要通过 web.xml 文件进行配置的。有两种方式一个是通过 servlet 一个是通过 web 容器的监听器。

 

 

 

总结:通过以上分析大家可以清楚的看到spring 是围绕着 beanFactory 来展开的。通过 bean 工厂来对在配置文件内的各个 bean 进行实例化装配。并在维护了一个容器来存储这些 bean ,其实内部就是一个 map 对象。 Map key 就是你在配置文件中的 beanid map value 就是 bean 的实例对象。使用时直接去容器中拿就可以了。

猜你喜欢

转载自997004049-qq-com.iteye.com/blog/1715436