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

时间:2022-08-09 04:11:27

Spring的IoC容器所起的作用,就是生产bean,并维持bean间的依赖关系。它会以某种方式加载Configuration Metadata(通常也就是XML格式的配置信息),然后根据这些信息绑定整个系统的对象,最终组装成一个可用的基于轻量级容器的应用系统。 

IoC实现上面要求的过程,可以分解为两步:

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

启动阶段分析:

1 加装资源文件

2 通过工具类(BeanDefinitionReader),分析资源文件

3 生成对应的BeanDefinition

4 将BeanDefinition注册到BeanDefinitionRegistry。

实例化阶段分析:

显示地调用container.getBean会触发bean的实例化

当实例化A的时候发现A依赖B,那么就会触发B的实例化。





当实例化某个对象的时候,首先会检查对象是否已经初始化,如果没有的话,初始化。

如果有依赖的对象,就注入之。

如果对象实现了某些回调接口,就根据接口装备它。

插手容器的启动

Spring提供了一种叫做BeanFactoryPostProcessor的容器扩展机制。该机制允许我们在容器实例化相应对象之前,对注册到容器的BeanDefinition所保存的信息做相应的修改。这就相当于在容器实现的第一阶段最后加入一道工序,让我们对最终的BeanDefinition做一些额外的操作,比如修改其中bean定义的某些属性,为bean定义增加其他信息等。 

使用BeanFactoryPostProcessor的方式,就是实现这个接口,然后在实现类里写逻辑。

我们先看看这个接口

public interface BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

上面的英文大家能看懂吧。allows for overriding or adding properties even to eager-initializing beans.

但是,因为Spring已经提供了几个现成的BeanFactoryPostProcessor实现类,所以,大多时候,我们很少自己去实现某个BeanFactoryPostProcessor。其中,org.springframework.beans. factory.config.PropertyPlaceholderConfigurer和org.springframework.beans.factory.config.Property OverrideConfigurer是两个比较常用的BeanFactoryPostProcessor。

PropertyPlaceholderConfigurer

通常情况下,我们不想将类似于系统管理相关的信息同业务对象相关的配置信息混杂到XML配置文件中,以免部署或者维护期间因为改动繁杂的XML配置文件而出现问题。我们会将一些数据库连接信息、邮件服务器等相关信息单独配置到一个properties文件中,这样,如果因系统资源变动的话,只需要关注这些简单properties配置文件即可。 

看例子:

容器使用BeanFactory

//声明将被后处理的BeanFactory实例
ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("..."));
//声明要使用的BeanFactoryPostProcessor
PropertyPlaceholderConfigurer propertyPostProcessor = new PropertyPlaceholderConfigurer();
propertyPostProcessor.setLocation(new ClassPathResource("..."));
//执行后处理操作
propertyPostProcessor.postProcessBeanFactory(beanFactory); 

使用Application

只需在xml文件中加上

...
<beans>
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="locations">
   <list>
      <value>conf/myjdbc.properties</value>
      <value>conf/mail.properties</value>
     </list>
   </property>
  </bean>
   ...
</beans>  

使用了propertyPlaceHolderConfigure后,xml中dataSource如下

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="url">
   <value>${jdbc.url}</value>
  </property>
  <property name="driverClassName">
   <value>${jdbc.driver}</value>
  </property>
  <property name="username">
   <value>${jdbc.username}</value>
  </property>
  <property name="password">
   <value>${jdbc.password}</value>
  </property>
  <property name="testOnBorrow">
   <value>true</value>
  </property>
  <property name="testOnReturn">
   <value>true</value>
  </property>
  ...
</bean>    
##myjdbc.properties
jdbc.url=jdbc:mysql://server/MAIN?useUnicode=true&characterEncoding=ms932&failOverReadOnly=false&roundRobinLoadBalance=true
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=your username
jdbc.password=your password 

xml中的${jdbc.url},就用properties中的jdbc.url相对应。

没有什么好讲的,就是这些死内容而已。

PropertyOverrideConfigurer

PropertyOverrideConfigurer干的事,就是修改从xml(无论是否包含propertyPlaceHolderConfigure的properties)加载过来的信息。

下面是针对dataSource定义给出的PropertyOverrideConfigurer的propeties文件配置信息:

##文件名是adjusment.properties
dataSource.minEvictableIdleTimeMillis=1000
dataSource.maxActive=50 

注意这个dataSource指的是beanName。***

这样,当按照如下代码,将PropertyOverrideConfigurer加载到容器之后,dataSource原来定

义的默认值就会被pool-adjustment.properties文件中的信息所覆盖:

<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
  <property name="location" value="adjusment.properties"/>
< /bean> 

PropertyOverrideConfigurer使用BeanFactory的方式,我就不再赘述了。

说实话,我并不觉得PropertyOverrideConfigurer有什么卵用。

CustomEditorConfigurer

java是强类型的一种语言:int,String,String[],Person等等等等。

而我们配置的xml,里面都是字面量,也就是说,spring拿到的原始数据全部是字符串。

那么,spring是怎么把字符串转成各种各样的类型呢?

用工具呗?

用什么工具?

CustomEditorConfigurer

Spring内部通过JavaBean的PropertyEditor来帮助进行String类型到其他类型的转换工作。只要为每种对象类型提供一个PropertyEditor,就可以根据该对象类型取得与其相对应的PropertyEditor来做具体的类型转换。Spring容器内部在做具体的类型转换的时候,会采用JavaBean框架内默认的PropertyEditor搜寻逻辑。

同时,Spring框架还提供了自身实现的一些Property-Editor。

  StringArrayPropertyEditor。该PropertyEditor会将符合CSV格式的字符串转换成String[]数组的形式,默认是以逗号(,)分隔的字符串,但可以指定自定义的字符串分隔

符。ByteArrayPropertyEditor、CharArrayPropertyEditor等都属于类似功能的Property- Editor,参照Javadoc可以取得相应的详细信息。 

  ClassEditor。根据String类型的class名称,直接将其转换成相应的Class对象,相当于通过Class.forName(String)完成的功效。可以通过String[]数组的形式传入需转换的值,以达到与提供的ClassArrayEditor同样的目的。 

  FileEditor。Spring提供的对应java.io.File类型的PropertyEditor。同属于对资源进行定位的PropertyEditor还有InputStreamEditor、URLEditor等。 

  LocaleEditor。针对java.util.Locale类型的PropertyEditor,格式可以参照Local-eEditor和Locale的Javadoc说明。 

  PatternEditor。针对JavaSE1.4之后才引入的java.util.regex.Pattern的Property-Editor,格式可以参照java.util.regex.Pattern类的Javadoc。

更多的关于CustomEditorConfigurer的资料参考 http://blog.csdn.net/zhoudaxia/article/details/36247883#t4

注意

按照JavaBeans的规范,JavaBeans的基础设施会在JavaBean相同类包下查找是否存在<JavaBean>Editor的类,如果存在,自动使用<JavaBean>Editor作为该JavaBean的PropertyEditor。

  如com.baobaotao.domain.UserEditor会自动成为com.baobaotao.domain.User对应的PropertyEditor。Spring也支持这个规范,也即如果采用这种规约命令PropertyEditor,就无须显式在CustomEditorConfigurer中注册了,Spring将自动查找并注册这个PropertyEditor。(甚至不用在xml中使用bean这个标签声明一个UserEditor)







如果是使用的是BeanFactory的实现,如XmlBeanFactory,就得通过硬编码的方式来应用CustomEditorConfigurer到容器中了。

XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource
CustomEditorConfigurer ceConfigurer = new CustomEditorConfigurer();
Map customerEditors = new HashMap();
customerEditors.put(java.util.Date.class, new DatePropertyEditor()); //以后凡是string转Date型的 都用DatePropertyEditor
ceConfigurer.setCustomEditors(customerEditors);
ceConfigurer.postProcessBeanFactory(beanFactory);   

DatePropertyEditor如下

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

如果我们想把某种格式的字符串转化为Person类,那么我们可以采用上面的方式,但是如果我们想把spring转化成date,我们又不能新建一个package名字叫java.util。

所以我们得让容器知道CustomEditorConfigurer的实现。

使用硬编码的方式,上面已经说了

如果是采用ApplicationContext,xml如下:

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

使用时:

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

大家注意,我给DateFoo传递的事一个"符合"DatePropertyEdit中datePattern格式的字符串"2007/10/16",这个字符串就是DatePropertyEdit中setAsTest方法中的参数

通过CustomerEditorConifgure,Spring已经知道了凡是String要转化成Date都去找datePropertyEdit... 后面的大家应该都能看懂了

不过在spring2.0之后,提倡使用,比较提倡使用propertyEditorRegistrars属性来指定自定义的PropertyEditor。这样一来我们就多了一步,实现PropertyEditorRegistrar 接口

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

然后在xml里这样注册:

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

再次注意:

我们知道有了上面的配置后,string转成date就会用datePrpertyEditor这个类

但是,这个类是什么时候被调用的呢?

答案是: 在getBean的时候

感谢glt

参考资料

http://blog.csdn.net/zhoudaxia/article/details/36247883

Spring揭秘 读书笔记 五 容器的启动的更多相关文章

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

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

  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揭秘 读书笔记 一 IoC初探

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

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

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

  7. spring揭秘 读书笔记 六 bean的一生

    我们知道,Spring容器具有对象的BeanDefinition来保存该对象实例化时需要的数据. 对象通过container.getBean()方法是才会初始化该对象. BeanFactory 我们知 ...

  8. Spring揭秘 读书笔记 四----方法注入

    我们知道,拥有prototype类型scope的bean,在请求方每次向容器请求该类型对象的时候,容器都会返回一个全新的该对象实例. 我们看下面的例子: public class MockNewsPe ...

  9. spring揭秘读书笔记----spring的ioc容器之BeanFactory

    spring的ioc容器是一种特殊的Ioc Service Provider(ioc服务提供者),如果把普通的ioc容器认为是工厂模式(其实很相似),那spring的ioc容器只是让这个工厂的功能更强 ...

随机推荐

  1. java&period;sql&period;SQLException&colon; 关闭的连接 解决办法

    程序如果长时间不进行数据库操作,那么数据源中的 Connection 很可能已经断开.其原因有可能是防火墙,或者连接的数据库设置的超时时间.这里使用的是 C3P0 连接 oracle 数据库,引起的异 ...

  2. ionic中input框禁止输入问题

    其实这个问题在之后沥青思路之后觉得还是挺好实现的,没有思路的时候真是找不到头绪~ 功能的描述为:当输入框中没有内容时,允许用户编辑:当其中有内容时不允许用户编辑,只有当用户点击编辑按钮后,才可允许编辑 ...

  3. 西南民大oj(矩阵快速幂)

    我的名字不可能那么难记 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 16            测试通过 : ...

  4. POJ 2299 Ultra-QuickSort (求序列的逆序对数)

    题意:废话了一大堆就是要你去求一个序列冒泡排序所需的交换的次数. 思路:实际上是要你去求一个序列的逆序队数 看案例: 9 1 0 5 4 9后面比它小的的数有4个 1后面有1个 0后面没有 5后面1个 ...

  5. CSS黄金三段--消除边框的影响

    以前常常因为padding.margin等影响了整个边框的大小,只能傻傻的算大小.现在的黄金三段真的是帮了大忙了,下面的代码放在CSS相应的内容中,就可以使得边框的大小就是你设置的width的属性值. ...

  6. zabbix监控到异常后自动执行对应命令

    zabbix可不仅仅只有监控功能,还支持远程执行命令,实现简单自动化运维 以下以监控mysql的3306端口为例,如该端口异常关闭,自动执行命令重启mysql 创建一个监听3306的监控项,键值按照这 ...

  7. linux 使用 vim 玩python

    vim 的配置文件默认是当前用户宿主目录下的.vimrc 文件.下列配置是常用 vim 进行 python 开 发的配置. " 高亮当前行 set cursorline " 将 T ...

  8. 理解OSI参考模型

    在一个视频网站上不小心搜到网络知识的视频,突然以前大学的没有真正接受的知识点,一下子豁然开朗,赶紧整理了下笔记. 一.OSI参考模型 自下而上:物理层(物理介质,比特流).数据链路层(网卡.交换机). ...

  9. phpstudy报告80端口被占用

    将所有的80端口修改为81后重启,还是不行

  10. js类的继承

    1.类式继承 首先要做的是创建构造函数.按惯例,其名称就是类名,首字母应该大写.在构造函数中,创建实例属性要用关键字this .类的方法则被添加到prototype对象中.要创建该类的实例,只需结合关 ...