关闭

Spring的BeanFactory的学习小节

1345人阅读 评论(0) 收藏 举报

以下内容是从书中摘录来的,但是我发现即使摘录一遍,对其内容的理解也会更加深入!
一、Spring装配Bean的过程
1. 实例化;
2. 设置属性值;
3. 如果实现了BeanNameAware接口,调用setBeanName设置Bean的ID或者Name;
4. 如果实现BeanFactoryAware接口,调用setBeanFactory 设置BeanFactory;
5. 如果实现ApplicationContextAware,调用setApplicationContext设置ApplicationContext
6. 调用BeanPostProcessor的预先初始化方法;
7. 调用InitializingBean的afterPropertiesSet()方法;
8. 调用定制init-method方法;
9. 调用BeanPostProcessor的后初始化方法;

Spring容器关闭过程
1. 调用DisposableBean的destroy();
2. 调用定制的destroy-method方法;

总结:
在Bean初始化的过程中最多有三次修改Bean的机会,实现InitializingBean或者定制init-method是一次机会,区别是一个与SpringFrameWork紧密偶合;实现BeanPostProcessor为Bean的修改提供了两次机会.
如果需要调用BeanFactor的一些特性,如发布事件等需要对BeanFactor或者ApplicationContext进行引用需实现BeanFactoryAware或者ApplicationContextAware.当然如果想得到自己的ID或者名字则实现BeanNameAware.
ApplicationContextAwareProcessor 是BeanPostProcessor的一个实现,将ApplicationContext传递给所有的实现ApplicationContextAware的Bean.

二、依赖注入
1、set依赖注入

代码
  1.  <property><ref bean="beanName"></property>  
  2. <property><ref local="beanName"></property>  
  3. <property><bean class="beanClass"/></property>  
  4. <property>  
  5.     <list>  
  6.         <value>bar</value>  
  7.         <ref bean="foo"/>  
  8.     </list>  
  9. </property>  
  10. <property>  
  11.     <set>  
  12.         <value>bar</value>  
  13.         <ref bean="foo"/>  
  14.     </set>  
  15. </property>  
  16. <property>  
  17.     <map>  
  18.         <entry key="key1"><!--主键只能是String-->  
  19.             <value>bar</value>  
  20.         </entry>  
  21.         <entry key="key2">  
  22.             <ref bean="foo"/>  
  23.         </entry>  
  24.     </map>  
  25. </property>  
  26. <property>  
  27.     <prop>  
  28.         <prop key="key1">foo</value>  
  29.         <prop key="key2">bar</value>  
  30.     </prop>  
  31. </property>       
  32. <property></null></property>  
<script type="text/javascript">render_code();</script>

 

2、constructor注入

代码
  1. <constructor-arg>  
  2.    <value>42</value>  
  3. </constructor-arg>  
  4. <constructor-arg>  
  5.    <bean ref="foo"/>  
  6. </constructor-arg>  
  7. <constructor-arg index="0">  
  8.    <bean ref="foo"/>  
  9. </constructor-arg>  
  10. <constructor-arg type="java.net.URL">  
  11.    <value>http://abc.com</value>  
  12. </constructor-arg>  
<script type="text/javascript">render_code();</script>

 

 

三、自动装配

有四种自动装配类型,byName,byType,constructor,autodetect,前两个是针对Set的自动装配,autodetect是由容器选择,在装配不成功(有重复情况)容器会抛异常而不是最先匹配原则。
缺省无自动装配,可设置缺省装配属性。
自动装配和非自动装配可混合使用。

 

四、BeanFactorPostProcessor
在BeanFactory载入所有Bean后,实例化Bean前,对BeanFactor做一些后处理工作,PropertyPlaceholderConfiger和CustomEditorConfigurer是SpringFrameWork自定义的BeanFactoryPostProcessor.

PropertyPlaceholderConfiger

代码
  1. <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfiger">  
  2.    <property name="location">jdbc.properties</property>  
  3. </bean>  
  4. <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfiger">  
  5.    <property name="locations">  
  6.       <list>  
  7.          <value>jdbc.properties</value>  
  8.          <value>security.properties</value>  
  9.       </list>  
  10. </bean>  
  11. <bean id="" class="">  
  12.     <property>  
  13.       <value>${database.url}</value>  
  14.     </property>  
  15. </bean>  
<script type="text/javascript">render_code();</script>

 

CustomerEditorConfigurer
继承java.beans.PropertyEditorSupport实现自己的TypeEditor,实现其中的setAsText方法,代码事例

代码
  1. public class PhoneEditor extends java.beans.   
  2. PropertyEditorSupport{   
  3.     public void setAsText(String textvalue)   
  4.     {   
  5.         ......   
  6.         PhoneNumber phone = new PhoneNumber();   
  7.         setValue(phone);   
  8.     }   
  9. }  
<script type="text/javascript">render_code();</script>

 

注册到SpringFrameWork

代码
  1. <bean id="customerEditorConfigurer" class="org.springframework.beans.factory.config.CustomerEditorConfiger">  
  2.   <property name="customEditors">  
  3.      <map>  
  4.        <entry key="com.Phone"><!---->  
  5.           <bean id="phoneEditor" class="PhoneEditor"/>  
  6.        </entry>     
  7.      </map>  
  8.   </property>  
  9. </bean>  
<script type="text/javascript">render_code();</script>

 

五、Event
系统事件ContextClosedEvent,ContextRefreshedEvent(初始化或者刷新时),RequestHandlerEvent Web请求被处理后。

接收事件的Bean 需实现ApplicationListener.

继承ApplicationEvent实现自己的Event,后由Bean调用context.publishEvent()发布事件,当然前提是你的Bean 要通过实现ApplicatonContextAware获得ApplicationContext.

 


 

13:09  |   永久链接  |   浏览 (17)  |   评论 (0)  |    收藏  |    
  缩略显示    

 

Spring是一个强大的Java应用框架,它广泛地应用于Java应用程序中,为Plain Old Java Objects(POJO)提供企业级服务。Spring利用依赖注入机制来简化工作,同时提高可测试性。其配置文件(通常是XML格式)中指定了Spring bean、依赖性以及bean所需的服务。但是,这些XML配置文件既冗长又不实用。对于需要定义大量Spring bean的大型项目来说,它们难以阅读和管理。
在本文中,我将向您展示12种用于Spring XML配置的最佳实践。其中的一些实践与其说是最佳实践,倒不如说是必要实践。注意,其他因素(如域模型的设置)也可能影响XML的配置,但是本文重点研究XML配置的可读性和可管理性。

1。避免使用自动绑定(autowiring)功能
Spring可以通过bean类的自省自动绑定依赖性,所以不必显式指明bean的属性和构造函数。Bean属性可以通过属性名称或类型匹配来实现自动绑定。构造函数通过类型匹配来实现自动绑定。甚至可以指定自动检测autowiring模式,它可以引导Spring选择一种适当的运行机制。先来看看下面的一个例子:
   
        class="com.lizjason.spring.OrderService"
        autowire="byName"/>
OrderService类的属性名在容器中用于匹配bean实例。自动绑定可能会节省一些键入工作量并减少混乱。但是在现实项目中不应该使用这种方式,因为它牺牲了配置的可读性和可维护性。许多指南和介绍中大肆吹捧自动绑定是Spring的一项极好的特性,而没有提到这一特性所带来的牺牲。依我来看,这就像Spring中的对象池(object-pooling),更大程度上只是宣传的噱头。对于精简XML配置文件来说,它是一个好办法,但它实际上增加了复杂性,尤其是在运行包含大量类声明的项目时。虽然Spring允许混合使用自动绑定和显式绑定,但这会使XML配置更加晦涩难懂。

2.使用命名约定
该原则对于Java编码也一样适用。在项目中使用清晰的、描述性的、一致的命名约定将非常有利于开发人员理解XML配置。例如,对于bean ID,可以按照Java类字段名约定来命名它。OrderServiceDAO实例的bean ID应该命名为orderServiceDAO。对于大型项目,可以在bean ID前面加上包名作为前缀。

3. 使用简洁形式
简洁形式避免了冗长,因为它将属性值和引用从子元素中移入属性中。例如下面的例子:
   
        class="com.lizjason.spring.OrderService">
       
            lizjason
       

       
           
       
   
可以使用简洁形式将上述代码重写为:
   
        class="com.lizjason.spring.OrderService">
       
            value="lizjason"/>
       
   

简洁形式自1.2版本起就可以使用。注意,对于,没有简洁形式。
简洁形式不但可以节约键入工作量,而且可以使XML配置文件更清晰。当一个配置文件中定义了大量的类时,它可以显著提高可读性。

4. 对于构造函数参数匹配,类型比下标好
当构造函数含有一个以上同种类型的参数,或者属性值的标签已经被占用时,Spring允许使用从0开始的下标来避免混淆。例如:
   
        class="com.lizjason.spring.BillingService">
       
       
   
利用type属性来编写会更好一些,如下:
   
        class="com.lizjason.spring.BillingService">
       
            value="lizjason"/>
       
   

使用index可以减少一些代码,但是与type属性相比,它更易于出错且难于阅读。只有在构造函数参数不明确的时候,才应该使用index。

5. 尽可能重用已定义的bean
Spring提供了一种类似于继承的机制来减少配置信息的复制并简化XML配置。定义一个子类,它就可以从父类那里继承配置信息,而父类实际上成为子类的一个模板。这就是大型项目中所谓的重用。只需在父类bean中设置abstract=true,然后在子bean中指定parent引用。例如:
   
        class="com.lizjason.spring.AbstractService">
       
            value="lizjason"/>
   

   
        parent="abstractService"
        class="com.lizjason.spring.ShippingService">
       
   

ShippingService类从abstractService类继承companyName属性的值——lizjason。如果一个bean没有指定类或工厂方法,那么这个bean便是抽象的。

6. 在导入时,首选通过ApplicationContext来汇编bean定义
像Ant脚本中的导入一样,Spring的import元素对于汇编模块化的bean定义来说是很有用的。例如:
   
       
       
       
            class="com.lizjason.spring.OrderService"/>
   

然而,相对于使用import在XML配置中进行预汇编,通过ApplicationContext来配置这些bean则显得更加灵活。使用ApplicationContext的话,XML配置也更易于管理。可以向ApplictionContext构造函数传递一组bean定义,如下:
    String[] serviceResources =
        {"orderServices.xml",
        "billingServices.xml",
        "shippingServices.xml"};
    ApplicationContext orderServiceContext = new
        ClassPathXmlApplicationContext(serviceResources);

7. 使用id作为bean标识符
可以指定一个id或名称来作为bean标识符。虽然使用id不能提高可读性,但是它可以利用XML分析程序来对bean引用进行验证。如果由于XML IDREF的约束而不能使用某个id,那么可以使用名称来作为bean的标识符。XML IDREF的约束是:id必须以字母(或者XML规范中定义的标点符号)开头,后面是字母、数字、连字符、下划线、冒号或句点。实际上,很少会遇到XML IDREF约束问题。

8. 在开发阶段使用依赖性检查(dependency-check)
可以在bean定义中为dependency-check属性设置一个非默认值,比如simple、objects或all,以便容器进行依赖性检查。当需要显式或通过自动绑定设置bean的全部属性(或某类属性)时,依赖性检查便显得很有用。
   
        class="com.lizjason.spring.OrderService"
        dependency-check="objects">
       
            value="lizjason"/>
       
   

在这个例子中,容器确保为orderService bean设置的属性不是primitives或collections。也可以为所有的bean设置默认依赖性检查,但是我们很少这样做,因为有些bean属性根本就不必设置。

9. 为每个配置文件添加首部注释
最好使用描述性的id和名称来取代XML配置文件中的内置注释。此外,添加一个配置文件首部也很有用,它可以概述文件中所定义的bean。可以选择将描述添加到description标签中。例如:
   
       
            This file defines billing service
            related beans and it depends on
            baseServices.xml,which provides
            service bean templates...
       
        ...
   
使用description标签的一个好处是可以轻松地利用工具从标签中选获取描述内容。

10. 对于更改,团队成员要积极交流
在重构Java代码时,需要随时更新配置文件并通知团队成员。XML配置文件也是代码,它们是应用程序的至关重要的部分,但是它们难于阅读和维护。大部分情况下,需要同时阅读XML配置文件和运行中的Java代码。

11. Setter注入优于构造函数注入
Spring提供了3种类型的依赖注入:构造函数注入(constructor injection)、setter注入(setter injection)和方法注入(method injection)。我们一般只用前两种。
   
        class="com.lizjason.spring.OrderService">
       
   

   
        class="com.lizjason.spring.BillingService">
       
            ref="billingDAO">
   

在这个例子中,orderService类使用的是构造函数注入,而BillingService类使用的是setter注入。构造函数注入可以确保bean不会在一个非法状态下被创建,但是setter注入更加灵活且更易于管理,尤其是在类包含许多属性并且其中一些可选的情况下。

12. 不要滥用依赖注入
最后一点,Spring ApplicationContext可以为您创建Java对象,但并不是所有的Java对象都应通过依赖注入来创建。例如,全局对象不应该通过ApplicationContext来创建。Spring是一个很棒的框架,但是,就可读性和易管理性而言,如果定义了大量bean,基于XML的配置就可能成为问题。过度使用依赖注入会使XML配置变得复杂且臃肿。要知道,借助于功能强大的IDE(如Eclipse和IntelliJ),Java代码比XML文件更加易读、易维护、易管理。

结束语
XML是通用的Spring配置方式。但如果定义了大量bean,基于XML的配置就会变得冗长而不实用。Spring提供了丰富的配置选项,恰当地利用其中的选项可以使XML配置更清晰,但是,有些选项(如autowiring)往往会降低配置文件的可读性和可维护性。遵循本文中所描述的最佳实践,将有助于您创建出清晰易读的XML配置文件。

 
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:2401300次
    • 积分:29811
    • 等级:
    • 排名:第172名
    • 原创:769篇
    • 转载:165篇
    • 译文:0篇
    • 评论:465条
    最新评论
    北京线点科技有限公司