1. Spring的IoC容器和IoC Service Provider的关系

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

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

 2. Spring提供了两种容器类型:BeanFactory和ApplicationContext。

 BeanFactory。

基础类型IoC容器,提供完整的IoC服务支持。如果没有特殊指定,默认采用延迟初始化策略(lazy-load)

只有当客户端对象需要访问容器中的某个受管对象的时候,才对该受管对象进行初始化以及依赖注入操作。所以,相对来说,容器启动初期速度较快,所需要的资源有限

对于资源有限,并且功能要求不是很严格的场景,BeanFactory是比较合适IoC容器选择。

 ApplicationContext。

ApplicationContext在BeanFactory的基础上构建,是相对比较高级的容器实现,

除了拥有BeanFactory的所有支持,ApplicationContext还提供了其他高级特性,比如事件发布、国际化信息支持等,这些会在后面详述。

ApplicationContext所管理的对象,在该类型容器启动之后,默认全部初始化并绑定完成。

所以,相对于BeanFactory来说,ApplicationContext要求更多的系统资源,

同时,因为在启动时就完成所有初始化,容器启动时间较之BeanFactory也会长一些。

在那些系统资源充足,并且要求更多功能的场景中,AlicationContext类型的容器是比较合适的选择


 4. BeanFactory和ApplicationContext 之间的关系

 

spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory_配置文件_02

5.BeanFactory介结 

BeanFactory可以完成作为IoC Service Provider的所有职责,包括业务对象的注册和对象间依赖关系的绑定。

对于独立的应用程序,只有主入口类才会跟容器的API直接耦合

 

6.容器启动三种代码写法:

不过,现在既然有了BeanFactory,我们通常只需将“生产线图纸”交给BeanFactory,让BeanFactory为我们生产一个FXNewsProvider,如以下代码所示: 

BeanFactory container = 
new XmlBeanFactory(new ClassPathResource("配置文件路径"));
FXNewsProvider newsProvider = (FXNewsProvider)container.getBean("djNewsProvider");
newsProvider.getAndPersistNews();
或者如以下代码所示:
ApplicationContext container = 
new ClassPathXmlApplicationContext("配置文件路径");
FXNewsProvider newsProvider = (FXNewsProvider)container.getBean("djNewsProvider");
newsProvider.getAndPersistNews();

亦或如以下代码所示:

ApplicationContext container =
new FileSystemXmlApplicationContext("配置文件路径");
FXNewsProvider newsProvider = (FXNewsProvider)container.getBean("djNewsProvider");
newsProvider.getAndPersistNews();

 

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

  直接编码方式,外部配置文件方式,注解方式

8.依赖绑定方式--直接编码方式

BeanFactory只是一个接口,我们最终需要一个该接口的实现来进行实际的Bean的管理,Default- ListableBeanFactory就是这么一个比较通用的BeanFactory实现类。DefaultListableBeanFactory除了间接地实现了BeanFactory接口,还实现了BeanDefinitionRegistry接口,该接口才是在BeanFactory的实现中担当Bean注册管理的角色。基本上,BeanFactory接口只定义如何访问容器内管理的Bean的方法,各个BeanFactory的具体实现类负责具体Bean的注册以及管理工作。BeanDefinitionRegistry接口定义抽象了Bean的注册逻辑。通常情况下,具体的BeanFactory实现类会实现这个接口来管理Bean的注册。它们之间的关系如图4-3所示。




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

9.依赖绑定方式--外部配置文件方式

Spring的IoC容器支持两种配置文件格式:Properties文件格式和XML文件格式。

当然,如果你愿意也可以引入自己的文件格式,前提是真的需要。采用外部配置文件时,Spring的IoC容器有一个统一的处理方式。

通常情况下,需要根据不同的外部配置文件格式,给出相应的BeanDefinitionReader实现类,

由BeanDefinitionReader的相应实现类负责将相应的配置文件内容读取并映射到BeanDefinition,

然后将映射后的BeanDefinition注册到一个BeanDefinitionRegistry,之后,BeanDefinitionRegistry即完成Bean的注册和加载。

当然,大部分工作,包括解析文件格式、装配BeanDefinition之类的工作,都是由BeanDefinitionReader的相应实现类来做的,BeanDefinitionRegistry只不过负责保管而已。

整个过程类似于如下
代码:
BeanDefinitionRegistry beanRegistry = <某个BeanDefinitionRegistry实现类,通常为➥
DefaultListableBeanFactory>;
BeanDefinitionReader beanDefinitionReader = new BeanDefinitionReaderImpl(beanRegistry);
beanDefinitionReader.loadBeanDefinitions("配置文件路径");
// 现在我们就取得了一个可用的Bea nDefinitionRegistry实例

10. Properties配置格式的加载PropertiesBeanDefinitionReader

Spring提供了org.springframework.beans.factory.support.PropertiesBeanDefinitionReader类用于Properties格式配置文件的加载,

所以,我们不用自己去实现BeanDefinitionReader,只要根据该类的读取规则,提供相应的配置文件即可。

Spring提供的PropertiesBeanDefinitionReader是按照Spring自己的文件配置规则进行加载的,

而同样的道理,你也可以按照自己的规则来提供相应的Properties配置文件。

只不过,现在需要实现你自己的“PropertiesBeanDefinitionReader”来读取并解析。这当然有“重新发明轮子”之嫌,不过,如果你只是想试验一下,也可以尝试哦。

11.XML配置格式的加载

如果FX新闻系统对象按照XML配置方式进行加载的话,配置文件内容如代码清单4-7所示。代码清单4-7 FX新闻系统相关类对应XML格式的配置内<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" ➥

"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="djNewsProvider" class="..FXNewsProvider">
<constructor-arg index="0">
<ref bean="djNewsListener"/>
</constructor-arg>
<constructor-arg index="1">
<ref bean="djNewsPersister"/>
</constructor-arg>
</bean>

<bean id="djNewsListener" class="..impl.DowJonesNewsListener">
</bean>
<bean id="djNewsPersister" class="..impl.DowJonesNewsPersister">
</bean>
</beans>

我想这段内容不需要特殊说明吧,应该比Properties文件的内容要更容易理解。如果想知道这些内
容背后的更多玄机,往后看吧!
有了XML配置文件,我们需要将其内容加载到相应的BeanFactory实现中,以供使用,如代码清
单4-8所示。
代码清单4-8 加载XML配置文件的BeanFactory的使用演示
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"));
}
与为 Properties配置文件格式提供PropertiesBeanDefinitionReader相对应,

Spring同样为XML格式的配置文件提供了现成的BeanDefinitionReader实现,即XmlBeanDefinitionReader。
XmlBeanDefinitionReader负责读取Spring指定格式的XML配置文件并解析,

之后将解析后的文件内容映射到相应的BeanDefinition,并加载到相应的BeanDefinitionRegistry中(在这里是DefaultListableBeanFactory)。这时,整个BeanFactory就可以放给客户端使用了。

 

除了提供XmlBeanDefinitionReader用于XML格式配置文件的加载,Spring还在DefaultListableBeanFactory的基础上构建了简化XML格式配置加载的XmlBeanFactory实现。从以上代码
最后注释掉的一行,你可以看到使用了XmlBeanFactory之后,完成XML的加载和BeanFactory的初
始化是多么简单。

12.  依赖绑定方式--注解方式

@Autowired是这里的主角,它的存在将告知Spring容器需要为当前对象注入哪些依赖对象。而

@Component则是配合Spring 2.5中新的classpath-scanning功能使用的。

现在我们只要再向Spring的配置文件中增加一个“触发器”,使用@Autowired和@Component标注的类就能获得依赖对象的注入了。

代码清单4-10 配置使用classpath-scanning功能

<?xml version="1.0" encoding="UTF-8"?> 

<beans xmlns="http://www.springframework.org/schema/beans" ➥

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ➥

xmlns:context="http://www.springframework.org/schema/context" ➥
xmlns:tx="http://www.springframework.org/schema/tx" ➥
xsi:schemaLocation="http://www.springframework.org/schema/beans ➥
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ➥
http://www.springframework.org/schema/context ➥
http://www.springframework.org/schema/context/spring-context-2.5.xsd ➥
http://www.springframework.org/schema/tx ➥
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<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");
newsProvider.getAndPersistNews();
}

 13 BeanFacotry的xml配置内容。

所有使用 XML 文件进行配置信息加载的 Spring IoC 容器,包括 BeanFactory 和

ApplicationContext的所有XML相应实现,都使用统一的XML格式。在Spring 2.0版本之前,这种格

式由Spring提供的DTD规定,也就是说,

所有的Spring容器加载的XML配置文件的头部,都需要以下形式的DOCTYPE声明: 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" ➥
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
...
</beans>

 

<beans>之唯我独尊

<beans>是XML配置文件中最顶层的元素,它下面可以包含0或者1个<description>和多个

<bean>以及<import>或者<alias>,

spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory_加载_04

 

 

<beans>作为所有<bean>的“统帅”,它拥有相应的属性(attribute)对所辖的<bean>进行统一

的默认行为设置,包括如下几个。

 spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory_加载_05

<description>

可以通过<description>在配置的文件中指定一些描述性的信息。

<import>

通常情况下,可以根据模块功能或者层次关系,将配置信息分门别类地放到多个配置文件中

<alias>

可以通过<alias>为某些<bean>起一些“外号”(别名)

构造方法注入的XML之道constructor-arg

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

<constructor-arg ref="djNewsListener"/>

<constructor-arg ref="djNewsPersister"/>

<bean id="mockBO" class="..MockBusinessObject">

<constructor-arg index="1" value="11111"/>

<constructor-arg index="0" value="22222"/>

</bean>

setter方法注入的XML之道

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

<property name="newsListener" ref="djNewsListener"/> 6

<property name="newPersistener" ref="djNewsPersister"/>

</bean>