spring的ioc容器是一种特殊的Ioc Service Provider(ioc服务提供者),如果把普通的ioc容器认为是工厂模式(其实很相似),那spring的ioc容器只是让这个工厂的功能更强大服务更全面,它们之间存在一定的交集。
 
Spring提供两种容器类型:BeanFactory和ApplicationContext
BeanFatory:基础类型IoC容器,提供完整的IoC服务支持。默认采用延迟初始化策略(lazy-load)。只有当客户端对象需要访问容器中的某个受管理对象的时候,才对该受管对象进行初始化以及依赖注入操作。相对来说,容器启动初期速度较快,所需要的资源有限。
ApplicationContext:基于BeanFactory,相对比较高级的容器实现。相比BeanFactory要求更多的系统资源,启动时候较长,但是拥有事件发布、国际化等高级特性。
 作为Spring提供的基本的Ioc容器,BeanFactory可以完成作为Ioc Service Provider的所有职责,包括业务对象的注册和对象建依赖关系的绑定。
BeanFactory就像一个汽车生产厂,你只需告诉它你需要哪些零件,然后在生产线的终点取得成品汽车就可以了。所以对于客户端来说,与BeanFactory打交道很简单。来看下源码:
public interface BeanFactory {

    String FACTORY_BEAN_PREFIX = "&";

    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;

    boolean containsBean(String name);

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;

    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);

}

我们应用的时候只用关心如何取得组装完成的对象的接口,即getBean()方法,这里提供了不同的参数以满足各种情况。所有对象之间的依赖关系就由BeanFactory来做了,那么如何做呢?

首先,通过xml告诉BeanFactory对象之间的依赖关系:

<beans>
<bean id="djNewsProvider" class=".../FXNewsProvider"></bean>
   ...
</beans>

然后BeanFactory就可以按照配置文件来注册对象和绑定依赖了:

BeanFactory container = new XmlBeanFactory(new ClassPatnResource("配置文件路径"));
FXNewsProvider djNewsProvider  = (FXNewsProvider)container.getBean("djNewsProvider"); 
djNewsProvider.getAndPersistNews();

BeanFactory的三种对象注册与依赖绑定方式:

1.直接编码

BeanFactory接口只定义如何访问容器内管理的Bean的方法,还需要具体实现类来负责Bean的注册及管理工作。

DefaultListableBeanFactory间接地实现了BeanFactory和BeanDefinitionRegistry接口。它们之间的关系如下:

打个比方,BeanDefinitionRegistry就像图书馆的书架,所有的书是放在书架上的。虽然你还书或者借书都是跟图书馆(也就是BeanFactory,或许BookFactory可能更好些)打交道,但书架才是图书馆存放各类图书的地方。所以,书架相对于图书馆来说,就是它的“BookDefinitionRegistry”。

每一个受管的对象,在容器中都会有一个BeanDefinition的实例(instance)与之相对应,该BeanDefinition的实例负责保存对象的所有必要信息,包括其对应的对象的class类型、是否是抽象类、构造方法参数以及其他属性等。当客户端向BeanFactory请求相应对象的时候,BeanFactory会通过这些信息为客户端返回一个完备可用的对象实例。

2.外部配置文件(两种格式:Properties和xml)

这种方式还是由BeanDefinitionRegistory负责管理注册的bean,不过解析文件、装配BeanDefinition等工作都由BeanDefinitionReader实现类完成。模拟xml配置文件流程:

public static void main(String[] args)
{
DefaultListableBeanFactory beanRegistry = new DefaultListableBeanFactory();
BeanFactory container = (BeanFactory)bindViaXMLFile(beanRegistry);
FXNewsProvider newsProvider = (FXNewsProvider)container.getBean("djNewsProvider");
newsProvider.getAndPersistNews();
} public static BeanFactory bindViaXMLFile(BeanDefinitionRegistry registry)
{
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
reader.loadBeanDefinitions("classpath:../news-config.xml");
   return(BeanFactory)registry;
  // 或者直接 
  //return new XmlBeanFactory(new ClassPathResource("../news-config.xml"));
}

3.注解方式

@Component
public class FXNewsProvider{
@Autowired
private IFXNewsListener newsListener;
@Autowired
private IFXNewsPersister newPersistener;
public FXNewsProvider(IFXNewsListener newsListner,IFXNewsPersister newsPersister)
  {
  this.newsListener = newsListner;
  this.newPersistener = newsPersister;
  }
  ...
}

@Autowired是这里的主角,它的存在将告知Spring容器需要为当前对象注入哪些依赖对象。而@Component则是配合Spring 2.5中新的classpath-scanning功能使用的。现在我们只要再向Spring的配置文件中增加一个“触发器”,使用@Autowired和@Component标注的类就能获得依赖对象的注入了。需要配置文件:

<context:component-scan base-package="cn.spring21.project.base.package"/></beans>

<context:component-scan/>会到指定的包(package)下面扫描标注有@Component的类,如果找到,则将它们添加到容器进行管理,并根据它们所标注的@Autowired为这些类注入符合条件的依赖对象。

然后就可以像之前加载配置文件一样的方式执行当前应用程序了:

public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("配置文件路径");
FXNewsProvider newsProvider = (FXNewsProvider)container.getBean("FXNewsProvider");4.3
newsProvider.getAndPersistNews();
}

整体来看spring Ioc容器
spring的Ioc容器的作用是以某种方式加载配置信息,然后根据这些信息绑定整个系统的对象,最终组装成一个可用的基于轻量级容器的应用系统。这个过程可以分为两个阶段:容器启动和Bean实例化。Spring的IoC容器在实现的时候,充分运用了这两个实现阶段的不同特点,在每个阶段都加入了相应的容器扩展点,以便我们可以根据具体场景的需要加入自定义的扩展逻辑。

1. 容器启动阶段
容器启动伊始,首先会通过某种途径加载Configuration MetaData。除了代码方式比较直接,在大部分情况下,容器需要依赖某些工具类(BeanDefinitionReader)对加载的Configuration MetaData进行解析和分析,并将分析后的信息编组为相应的BeanDefinition,最后把这些保存了bean定义必要信息的BeanDefinition,注册到相应的BeanDefinitionRegistry,这样容器启动工作就完成了。

总地来说,该阶段所做的工作可以认为是准备性的,重点更加侧重于对象管理信息的收集。当然,一些验证性或者辅助性的工作也可以在这个阶段完成。

2. Bean实例化阶段
经过第一阶段,现在所有的bean定义信息都通过BeanDefinition的方式注册到了BeanDefinitionRegistry中。当某个请求方通过容器的getBean方法明确地请求某个对象,或者因依赖关系容器需要隐式地调用getBean方法时,就会触发第二阶段的活动。该阶段,容器会首先检查所请求的对象之前是否已经初始化。如果没有,则会根据注册的BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。如果该对象实现了某些回调接口,也会根据回调接口的要求来装配它。当该对象装配完毕之后,容器会立即将其返回请求方使用。如果说第一阶段只是根据图纸装配生产线的话,那么第二阶段就是使用装配好的生产线来生产具体的产品了。

总结:本节主要介绍了spring的两种容器类型,然后又介绍了最基本的BeanFactory的三种对象注册和依赖绑定方式,其实和一般的Ioc Service Provider支持的三种方式一样。

spring揭秘读书笔记----spring的ioc容器之BeanFactory的更多相关文章

  1. spring揭秘 读书笔记 一 IoC初探

    本文是王福强所著<<spring揭秘>>一书的读书笔记 ioc的基本概念 一个例子 我们看下面这个类,getAndPersistNews方法干了四件事 1 通过newsList ...

  2. spring揭秘 读书笔记 二 BeanFactory的对象注册与依赖绑定

    本文是王福强所著<<spring揭秘>>一书的读书笔记 我们前面就说过,Spring的IoC容器时一个IoC Service Provider,而且IoC Service Pr ...

  3. spring揭秘 读书笔记 二 BeanFactory的对象注冊与依赖绑定

    本文是王福强所著<<spring揭秘>>一书的读书笔记 我们前面就说过,Spring的IoC容器时一个IoC Service Provider,并且IoC Service Pr ...

  4. Spring揭秘 读书笔记 三 bean的scope与FactoryBean

    本书可作为王富强所著<<Spring揭秘>>一书的读书笔记  第四章 BeanFactory的xml之旅 bean的scope scope有时被翻译为"作用域&quo ...

  5. Spring揭秘读书笔记 八 数据访问异常体系

    这篇博客 来自spring揭秘一书的第十三章 为什么要有访问异常都有一个体系,这个我们得从DAO模式说起. DAO模式 任何一个系统,不管是一个最简单的小系统,还是大规模的系统,都得跟数据打交道,说白 ...

  6. spring揭秘读书笔记----ioc的基本概念

    在看ico概念之前,先想一下我们平常需要依赖某个类时会怎么做? 无非是在要用到的地方写如下代码: Person person = new Person(); //然后就可以用person对象来获取Pe ...

  7. spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory

    1. Spring的IoC容器和IoC Service Provider的关系 Spring的IoC容器和IoC Service Provider所提供的服务之间存在一定的交集,二者的关系如图4-1所 ...

  8. Spring揭秘 读书笔记 五 容器的启动

    Spring的IoC容器所起的作用,就是生产bean,并维持bean间的依赖关系.它会以某种方式加载Configuration Metadata(通常也就是XML格式的配置信息),然后根据这些信息绑定 ...

  9. Spring揭秘 读书笔记 七 BeanFactory的启动分析

    首先,先看我自己画的BeanFactory启动时的时序图. 第一次接触时序图,可能有些地方画的不是很符合时序图的规则,大家只关注调用顺序即可. public static void main(Stri ...

随机推荐

  1. linux查看cpu内存信息

    # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数 cat /proc/cpuinfo| ...

  2. [JSOI2008]Star War

    星球之间互相直接或间接地连接帝国开始使用死星有计划地摧毁反抗军占领的星球给出星球间隧道的连通情况,已经帝国打击的顺序要求以尽量快的速度求出每一次打击之后反抗军占据的星球的联通快的个数(若两个星球,直接 ...

  3. 单调队列练习题(oj p1157 p1158 p1159)

    p1157是很气人的...自从评测机挂了后,速度就特别慢,cin已经过不了了,然而我不知道,就各种**的提交 惨兮兮惨兮兮,这还是开了小号(通过率堪忧.jpg...)... 思路就是单调队列维护,用队 ...

  4. 素数路(prime) (BFS)

    问题 C: 素数路(prime) 时间限制: 1 Sec  内存限制: 64 MB提交: 8  解决: 5[提交][状态][讨论版] 题目描述 已知一个四位的素数,要求每次修改其中的一位,并且要保证修 ...

  5. matlab的table数据类型初步接触

    由于数据分析,接触到cell的使用,字符串的使用以及ASCII的使用,但是发现在matlab中进行这样的操作相对繁琐,然后知道了table数据类型,是matlab新的数据类型,于2013版开始引入.据 ...

  6. [CTSC2017]密钥

    传送门:http://uoj.ac/problem/297 “无论哪场比赛,都要相信题目是水的” 这不仅是HNOI2018D2T3的教训,也是这题的教训,思维定势真的很可怕. 普及组水题,真是愧对CT ...

  7. [LOJ6433]最大前缀和

    深刻感受到自己的水平和机房里的其他人相差甚远,他们都是随手秒这个题的... $n$很小,考虑状压DP 当一个序列在某个位置取到最大前缀和后,意味着如果把后面的数抽出来单独成序列,那么它的每个前缀和都$ ...

  8. 【二分图】【最大匹配】【匈牙利算法】bzoj1191 [HNOI2006]超级英雄Hero

    裸的最大匹配. #include<cstdio> #include<vector> #include<cstring> using namespace std; v ...

  9. Java如何实现系统监控、系统信息收集(转

    Java如何实现系统监控.系统信息收集.sigar开源API的学习 系统监控(1) Jar资源下载:http://download.csdn.net/detail/yixiaoping/4903853 ...

  10. 1.7(java学习笔记)package和import

    package package主要用于管理类,在java中同一个包下不能有相同的类名,可有时项目总会出现很多同名的类,这时就需要通过包来管理类.不同的包下可以有相同的类名. 包就有点类似于文件夹,不同 ...