通过ioc容器,对象依赖关系的管理被反转了,转到ioc容器中来了,对象之间的依赖关系由ioc容器进行管理。这里的反转,指的是责任的反转。
作为一个ioc容器,也需要为它的具体实现指定基本的功能规范,这个功能规范的设计表现为BeanFactory,它是spring为用户提供的ioc容器所设定的最基本的功能规范。
BeanDefinition来管理基于spring的应用中各种对象以及他们之间的相互依赖关系。它抽象了我们对Bean的定义,是让容器起作用的主要数据类型。这些BeanDefinition就像是水桶里的水。
我们要注意区分FactoryBean和BeanFactory,FactoryBean指的是工厂类实例化后的对象,而BeanFactory是生产类的工厂。
BeanFactory中的接口名单
这个BeanFactory提供了使用IOC的容器规范,在这个基础上spring提供了符合这个ioc容器接口的一系列的容器的实现供开发使用。BeanFactory的继承体系如下:AutowireCapableBeanFactory->AbstractAutowireCapableBeanFactory->DefaultListableBeanFactory->xmlBeanFactory。 XmlBeanFactory有一个明显的特征,就是他只提供最基本的IOC容器功能,可以读取Xml形式定义的BeanDefinition。BeanFactory是ioc容器的基本形式,而applicationContext实现是IOC容器的高级表现形式。
xmlBeanFactory在继承了DefaultListableBeanFactory容器的功能同时,给DefaultListableBeanFactory增加了一个与xml相关的BeanFactory,他可以读取以xml文件方式定义的BeanDefinition的一个ioc容器。
xmlBeanFactory如何实现读取XML文件定义的BeanDefinition呢?它初始化了一个XmlBeanDefinitionReader对象,有了这个对象就可以读取xml文件了。
在构造XmlBeanFactory这个IOC容器时,需要制定Bean、Definition的信息来源,这个来源需要封装成Spring中的Resource类。Resource是spring用来封装IO操作的类。比如我们的BeanDefinition信息是以xml文件形式存在的,那么可以使用像ClassPathResource res = new ClassPathResource(“bean.xml”);这样具体的ClassPathResource来构造需要的Resource。然后作为构造参数传递给XmlBeanFactory构造函数。这样IOc容器就可以方便的定位到需要BeanDefinition信息来对Bean完成容器化的初始化和依赖注入的过程。
如何编程式使用Ioc容器:
①ClassPathResource res = new ClassPathResource(“bean.xml”);
②DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
③XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
④reader.loadBeanDefinition(res);
①:创建IoC配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息。
②:创建一个BeanFactory,这里使用DefaultListableBeanFactory。
③:创建一个载入BeanDefinition的读取器,这里使用XMLBeanDefinitionReader来载入xml文件形式的BeanDefinition,通过一个回调配置给BeanFactory。
④:从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成。完成整个载入和注册Bean定义之后,需要的Ioc容器就建立起来了,这个时候Ioc容器就可以直接用了。
ApplicationContext是一个高级形态意义的IoC容器。因为他继承了很多父类,拥有了很多父类的功能。
如:EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver(继承了ResourceLoader)。
初始化过程包括:BeanDefinition的Resource定位、载入、注册这三个基本过程。
①定位:BeanDefinition的资源定位由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形式的BeanDefinition的使用提供了统一接口,比如文件系统中Bean定义信息可以使用FileSystemResource来进行抽象;在类路径中可以使用前面提到的ClassPathResource来使用。这个过程类似于寻找数据的过程。
②载入:BeanDefinition的载入,该载入过程把用户定义好的Bean表示成IoC容器的内部数据结构,而这个容器的内部的数据结构就是BeanDefinition。
③注册:向IoC容器注册这些BeanDefinition的过程,这个过程是通过调用BeanDefinitionRegistry接口的实现来完成的。Ioc内部是使用一个HashMap来维持这些BeanDefinition数据的。
注意:Ioc容器和上下文初始化一般不包括Bean的依赖注入的实现。一般而言,依赖注入发生在应用第一次向容器通过getBean索取Bean时。但是有例外:ioc容器有一个预实例化的配置,可以通过在Bean定义信息中的lazyInit属性来设定,有了这个预实例化的配置,使得这个Bean的依赖注入在Ioc容器初始化时就预先完成了。
注册的过程是发生在DefaultListableBeanFactory中的registerBeanDefinition方法中。填充到concurrentHashMap的definitionMap中
首先依赖注入是发生在用户第一次向Ioc索要bean时触发的,但是也有例外,如lazy_init属性可以完成对Bean的预实例化具体流程见流程图
预实例化时发生在AbstractApplicationContext中的refresh方法中实现的
最后实在DefaultListableBeanFactory中的preInstantiateSingletons中实现的
FactoryBean是一个能生产或修饰对象生成的工厂Bean。一个Bean如果实现了FactoryBean接口,那么根据该Bean的名称获取到的实际上是getObject()返回的对象,而不是这个Bean自身实例,如果要获取这个Bean自身实例,那么需要在名称前面加上’&'符号。
https://www.cnblogs.com/guitu18/p/11284894.html
spring主要通过jdbcTemplate来操作数据库
spring与ibatis的结合,使用的是FactoryBean来完成对iBatis的配置,结合了Template来封装相应的操作