Spring容器管理Bean
在上一篇中介绍了spring的2类容器:Bean工厂和ApplicationContext应用上下文。
今天我将再次对上篇文档进行补充和拓展,以及不同spring版本之间的Bean配置上的一些区别:
1. ApplicationContext应用上下文是对Bean工厂的功能性拓展。为什么这样说:有几点很重要已经在上文中有介绍,还有一点很重要的区别就是:ApplicationContext应用上下文对单例Bean的特殊处理。
在spring3.0中,已经把bean标签的singleton这个属性去掉,取而代之的是scrope属性,他又几个可选择,我只介绍”singleton”和”prototype”2个属性值。
a. singleton:容器只管理一个scrope设置为singleton值的实例,对于多次请求返回同一实例的引用。必须注意的是:在Bean工厂中只有当有请求需要时才创建该唯一实例,而在ApplicationContext应用上下文里,当载入文件信息的时候就先创建该实例。
b. prototype:对于每一次请求需要不然什么类型的容器都会再次创建一个新实例返回给用户。
也就是说:对于非Singleton的Bean都是在请求到来时创建它的实例。(bean标签的缺省值是:singleton);
2. 现在我将介绍返回Bean之前对bean的一些后处理操作:
为了让广大观众不至于把概念混淆:我先介绍下我将用到的几个比较容易混淆的概念:
a. 装载:或者说是组装,指的是在创建对象的时候通过Set方式给对象补充设置属性(当然前提配置文件里定义了Set注入)。
b. 实例化:或者说初始化我这里所说的实例化是指对象创建成功,并且已注入了相关属性,然后调用内部的一些其他代码进行后续的一些操作,那么我们可以简单理解为是对象的实例化过程。
现在我们的后处理操作就是发生在实例化这段时间(也就是装载完场之后,到返回给用户之前)。
先介绍下实例化:
实例化有2中实现方式:
a. 实现spring的InitializingBean接口,该接口有一个afterPropertiesSet()方法,该方法不需要传参,也就是不能用这个方法来进行传值操作。还有一个好处就是Bean如果实现了这个接口,则不需要在bean标签里配置初始化方法。
b. 也可自定义初始化方法,只需在bean标签里添加一个init-method=””属性即可。
同理,既然有初始化的方法,那必然有销毁的方法,销毁同样有2种方式实现:
a. 实现spring的DisposableBean接口,该接口也有一个方法destroy(),该方法在销毁Bean方法时效用,也不需要在bean标签里配置。
b. 也可自定义销毁方法,同样必须在标签里添加一个属性:destroy-method=””。
所谓后处理操作:是spring专门提供给用户在bean的生命周期中检查或者修改bean的配置,spring其实也是很小气的,他只给用户2此这样的机会,当然要想拥有2次这样的机会必须的实现spring的一个接口BeanPostProcessor,它有2个方法,如下:
public abstract Object postProcessBeforeInitialization(Object obj, String s) throws BeansException;
public abstractpostProcessAfterInitialization(Object obj, String s) throws BeansException;
初始化方法和后处理方法的执行顺序如下:
postProcessBeforeInitialization()à初始化方法àpostProcessAfterInitialization()
注意一般情况下新建一个类用于实现后处理接口:然后把需要后处理的对象做参数传到那2个接口方法里,这样就可以对象的检查和修改等后处理操作了,还有一个参数是前一个参数在配置文件里的name;
在实现这个接口的时候还有一点非常重要,那就是方法返回值问题,必须把第一个参数返回回去,否则,该对象可能无法在容器中获得.
怎么通知spring让它去管理后处理bean呢?这就要对后处理bean进行注册了,当注册之后,则后处理代码将作用在所有该容器里的Bean(这样不好吧,万一我只想作用一个呢?)。
1. 如果运用的是Bean工厂,则必须先创建一个后处理bean的对象,然后调用factory的addBeanPostProcessor()方法把后处理bean添加进去。
2. 如果是ApplicationContext应用上下文,则只需像普通Bean一样配置即可。
完成了以上步骤,spring即可管理后操作代码。
Spring自身有自带的后处理bean,其实也是实现了BeanPostProcessor接口
ApplicationContextAwareProcessor和DefaultAdvisorAutoProxyCreator,等等还有很多,我会在以后篇幅里介绍。
下面介绍一个Bean工厂后处理接口BeanFactoryPostProcessor,如下是它的方法:
public abstract void postProcessBeanFactory(ConfigurableListableBeanFactory configurablelistablebeanfactory) throws BeansException;
见名知意,它是在Bean工厂载入所有Bean文件的定义后,在装载Bean之前掉用的对Bean工厂进行后处理的方法。他只需想普通Bean一样配置,并且只能运用在ApplicationContext应用上下文中。
以下是它的诸多实现中的最重要的2个:
a. PropertyPlaceholderConfigurer:它的一个很重要的作用就是,可以将松散配置的Bean组装起来。举个最简单的例子:一个类里可能需要多个属性,这些属性又都是分散在多个配置文件中,这时候就可以通过PropertyPlaceholderConfigurer来告诉spring从外部属性文件装载信息。当然它也必须在配置文件里配置:
<bean id=”configurer” name=” org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>
//注意只引用一个文件name可以是“location”,当然该标签下子标签也只能<value>,并且只能是一个。下面是引用多个外部文件的方式
<property name=”locations”>
<list>
<value>XXXXX<value>
<value>XXXXX<value>
….
</list>
</property>
在需要引用外部文件属性信息的Bean里的属性可以这样配置:
<property name=””>
<value>${xxxxx}</value> 引入的是外部文件的信息。
</property>
b. CustomEditorConfigurer:用于注册用于将定制的属性编辑器装载到BeanFactory中,或者也可以通过硬编码将编辑器注册到容器中。
下面我将介绍所谓的编辑器:
Java.beans.PropertyEditor接口能将String类型映射成非String类型,它有2个比较感兴趣的方法:getAsText()和setAsText(String value),可调用setAsText方法将String类型的数据set到非String类型的属性里。
PropertyEditor有一个很好的实现java.beans.PropertyEditorSupport,spring自带的几种编辑器都是继承自它,当然你也可以继承PropertyEditorSupport来拓展自己的编辑器。
当制定好的编辑器通过CustomEditorConfigurer注册到BeanFactory中(如果是Bean工厂,则可以通过类似上面注册后处理代码的方式注册,如果是ApplicationContext应用上下文则自需在配置文件里配置)。具体怎么配置自己查阅资料,不多将了哈~
今天主要是理论上的理解,代码比较少,但如果要真正理解上面的概念,还是写几个类自己测试,边学边写才是最好的学习方法……