MicroFish

Open & Open hits
随笔 - 33, 文章 - 2, 评论 - 4, 引用 - 0
数据加载中……

《Pro Spring》学习笔记(6)--基础进阶(1)

 

      Spring不仅提供了基本的IOC功能,借助于BeanFactory以及其它组件,我们还可以使用其它一些更高级的功能。但是需要注意的是,使用这些高级功能,将不可避免的使得我们的工程依赖于Spring。这些高级功能大致包括:管理bean的生命周期,让bean感知Spring(Spring aware),使用方法注入,使用FactoryBean,使用PropertyEditor以及了解Spring的ApplicationContext
      有时候,我们需要在bean的生命周期中的某些阶段做一些相应的操作(类似于Servlet和EJB),像其它IOC容器一样,Spring也提供了管理bean生命周期的功能。两个主要的阶段是:
post-initialization(bean初始化之后)和pre-destruction(bean销毁之前).
      post-initialization是指在Spring完成了bean的所有依赖注入以及相应的检测之后,
      pre-destruction是指在Spring销毁bean之前。
      post-initialization和pre-destruction只能应用于sigleton模式的bean,因为非sigleton的bean的生命周期并不由Spring控制(它们是由JVM控制的)。
      Spring提供了两种机制来实现bean生命周期的管理:基于接口的和基于指定方法的。
      使用基于接口的机制,我们需要实现Spring的相关接口,然后,Spring会使用回调机制在指定的阶段调用接口中定义的方法,从而实现bean生命周期的管理。而使用基于指定方法的机制,我们需要在BeanFactory的配置中指定相应的方法名称,Spring会使用Java的反射机制在指定的阶段调用我们指定的方法,从而实现bean生命周期的管理。
      选择哪种机制取决于我们的工程的需要。基于接口的机制要求我们实现Spring的接口,这会带来对Spring的依赖,但是当我们定义了很多相同类型的bean时,使用基于接口的机制可以免去我们为每个bean定义指定相应方法的麻烦。基于指定方法的机制则可以让我们避免对Spring的依赖,这在当我们使用第三方的类库(因此,我们无法修改其代码来实现Spring的接口)时是非常有用的。
      以post-initialization为例:
      使用基于接口的机制,我们需要实现Spring的InitializingBean接口的afterPropertiesSet方法
      public class SimpleBeanWithInterface implements InitializingBean {
          ...
          public void afterPropertiesSet() throws Exception {
              ...
          }
          ...
      }
      <beans>
         <bean id="simpleBean1"
         class="com.apress.prospring.ch5.lifecycle.SimpleBeanWithInterface">
             ...
         </bean>
      </beans>
      使用基于指定方法的机制,我们只需在BeanFactory的配置中指定相应的方法名称
      <beans>
          <bean id="simpleBean1"
          class="com.apress.prospring.ch5.lifecycle.SimpleBean"
          init-method="init">
              ...
          </bean>
      </beans>

      SimpleBean中包含对应的init方法
      public class SimpleBean {
          ...
          public void init() {
              ...
          }
          ...
      }

      需要注意的是,init方法必须不包含任何参数,尽管我们可以为init方法指定任意的返回值,但Spring会忽略它,因此最好的做法是在init方法中抛出异常来表明初始化失败了。
      我们也可以同时使用这两种机制,这时,Spring会先调用InitializingBean接口的afterPropertiesSet方法,再调用我们自己指定的init方法。
      相对的,pre-destruction使用DisposableBean接口的destroy方法和bean标签的destroy-method属性
      相对于依赖查找(Dependency Lookup),依赖注入(Dependency Injection)最大的卖点就是容器的无关性,但是有时候,我们确实需要和容器进行一些交互,例如访问BeanFactory或者是获得bean的名称等。
      为了获得bean的名称,我们需要实现Spring的BeanNameAware接口,BeanNameAware只有一个方法,void setBeanName(String name),只要我们的bean实现了BeanNameAware接口,Spring就会在bean配置结束,其它生命周期相关的回调函数(initialization或者 destroy)调用之前,回调该方法置入bean的名称。
      类似的,为了访问beanFactory,我们需要实现Spring的BeanFactoryAware接口的
void setBeanFactory(BeanFactory factory)方法。

posted @ 2006-12-21 10:23 刘璐 阅读(351) | 评论 (0)编辑 收藏

《Pro Spring》学习笔记(5)--配置BeanFactory(2)

 

      BeanFactory中的每个bean都必须至少有一个唯一的名字,Spring为了灵活的支持各种情形,使用了相对复杂的命名体系。如果我们为bean指定了id属性,那么id属性的值将成为bean的名称,如果没有指定id属性,Spring将使用name属性的第一个值(多个值用逗号或者分号分隔)作为bean的名称,如果name属性也没有指定,Spring将使用bean的类名(包括package的完整类名)来作为bean的名称,对于多个bean使用相同类名的情况,Spring会在类名后面添加#2,#3等序号来加以区别。不管怎么说,使用id属性来指定bean的名称总是一个不错的选择。
     在Spring中,所有bean默认都是以单例(singleton)形态存在的,也就是说我们通过BeanFactory的getBean方法获取的同一名称的bean是完全相同的,即:beanFactory.getBean("name")==beanFactory.getBean("name")。更改bean的形态为非singleton(原型的,prototype)是很容易的,只需在bean标签中,指定singleton属性为false就可以了。
<bean id="nonSingleton" class="java.lang.String" singleton="false">
    ...
</bean>
      为了简化配置,Spring还提供了自动组装(Auto-Wiring)bean的功能,有四种自动组装方式:根据名称(byName),根据类型(byType),构造子(Constructor)以及自动侦测(autodetect)。
      使用根据名称自动组装时,Spring根据bean的属性的名称去寻找同名的bean配置。
      使用根据类型自动组装时,Spring根据bean的属性的类型去寻找同类型的bean配置,如果有多个同类型的bean配置,那么Spring将会抛出异常,以表示无法确定使用哪个。
      使用构造子自动组装和使用根据类型自动组装比较类似,需要注意的是,使用构造子自动组装时,Spring会匹配尽可能多的参数。例如,我们有一个bean拥有两个构造函数,第一个接收一个String类型的参数,第二个接收一个String类型和一个Integer类型的参数,这时,如果在beanFactory的配置文件中有一个String类型的bean配置和一个Integer类型的bean配置,那么Spring将会使用第二个拥有两个参数的构造函数。
       使用自动侦测组装时,Spring会在根据类型自动组装和根据构造子自动组装之间自动作出选择,依据是:如果bean拥有默认的(无参数的)构造函数,那么Spring使用根据类型自动组装的方式,否则,使用根据构造子自动组装的方式。
       有时候,我们可能会有多个bean拥有共同的类型,或是实现一些共同的接口,因此它们会有一些相同的配置,如果能将这些相同的配置提取出来,各个bean只要继承这些相同的配置,然后添加自己特有的配置,将会大大减少重复的配置,降低发生错误的可能。Spring的bean继承机制就是出于这样的目的而提供的。在Spring中,我们可以将这些相同的配置提取出来,配置成一个parent bean,然后各个bean(child bean)可以继承parent bean,在child bean中,可以覆写parent bean中的配置,也可以添加自己的配置。parent bean是通过child bean的bean标签的parent属性来指定的。
<bean id="inheritParent" class="com.apress.prospring.ch4.inheritance.SimpleBean">
    <property name="name">
        <value>Rob Harrop</value>
    </property>
    <property name="age">
        <value>22</value>
    </property>
</bean>
<bean id="inheritChild" class="com.apress.prospring.ch4.inheritance.SimpleBean"
parent="inheritParent">
    <property name="age">
        <value>35</value>
    </property>
</bean>
      需要注意的是,bean的继承体系并不完全等同于java的类继承体系,我们完全可以在数个拥有相同类型的bean上使用继承,这不会带来任何问题。因此,相对于java的继承体系来说,Spring 的bean继承体系更类似于模板类型。

posted @ 2006-12-21 10:22 刘璐 阅读(454) | 评论 (0)编辑 收藏

《Pro Spring》学习笔记(4)--配置BeanFactory(1)

 

      Spring使用spring-beans.dtd文件来定义BeanFactory的XML配置规范。可以在http://www.springframework.org/dtd/spring-beans.dtd找到该dtd文件,当然,Spring的下载文件中也已经包含了该dtd文件。它被放在dist文件夹中。
      配置文件的根元素是beans,每个组件使用bean元素来定义,bean元素可以有许多属性,其中有两个是必须的:idclass(这里说的id是必须的并不意味着在配置文件中必须指定id,后面会详细说明)。id表示组件的默认名称,class表示组件的类型。
      如果使用设值注入,则需要使用property子标签,来指定组件的属性。
<bean id="renderer" class="com.apress.prospring.ch2.StandardOutMessageRenderer">
    <property name="messageProvider">
        <ref local="provider"/>
    </property>
</bean>
      使用构造子注入时,则使用constructor-arg子标签,来指定构造函数的参数。
<bean id="provider" class="com.apress.prospring.ch4.ConfigurableMessageProvider">
    <constructor-arg>
        <value>This is a configurable message</value>
    </constructor-arg>
</bean>
      当构造函数有多个参数时,可以使用constructor-arg标签的index属性,index属性的值从0开始。
<bean id="provider" class="com.apress.prospring.ch4.ConfigurableMessageProvider">
    <constructor-arg index="0">
        <value>first parameter</value>
    </constructor-arg>
    <constructor-arg index="1">
        <value>second parameter</value>
    </constructor-arg>

</bean>
     在使用构造子注入时,需要注意的问题是要避免构造子冲突的情况发生。考虑下面的情况:
public class ConstructorConfusion {
    public ConstructorConfusion(String someValue) {
        System.out.println("ConstructorConfusion(String) called");
    }
    public ConstructorConfusion(int someValue) {
        System.out.println("ConstructorConfusion(int) called");
    }
}
     使用如下配置文件
<bean id="constructorConfusion" class="com.apress.prospring.ch4.ConstructorConfusion">
    <constructor-arg>
        <value>90</value>
    </constructor-arg>
</bean>
     那么,当实例化组件constructorConfusion时,将输出ConstructorConfusion(String) called,也就是说参数类型为String的构造函数被调用了,这显然不符合我们的要求。为了让Spring调用参数为int的构造函数来实例化组件constructorConfusion,我们需要在配置文件中明确的告诉Spring,需要使用哪个构造函数,这需要使用constructor-argtype属性。
<bean id="constructorConfusion" class="com.apress.prospring.ch4.ConstructorConfusion">
    <constructor-arg type="int">
        <value>90</value>
    </constructor-arg>
</bean>
     我们不仅可以构造单个BeanFactory,而且可以建立有继承关系的多个BeanFactory。只需要将父BeanFactory作为参数传给子BeanFactory的构造函数即可。
BeanFactory parent =
    new XmlBeanFactory(new FileSystemResource("./ch4/src/conf/parent.xml"));
BeanFactory child =
    new XmlBeanFactory(new FileSystemResource("./ch4/src/conf/beans.xml"), parent);
     如果子BeanFactory和父BeanFactory中含有名称相同的Bean,那么在子BeanFactory中使用
<ref bean="sameNameBean"/>引用的将是子BeanFactory中的bean,为了引用父BeanFactory中的bean,我们需要使用ref标签的parent属性,<ref parent="sameNameBean"/>
     为了注入集合属性,Spring提供了list,map,setprops标签,分别对应List,Map,Set和Properties,我们甚至可以嵌套的使用它们(List of Maps of Sets of Lists)。
<bean id="injectCollection" class="com.apress.prospring.ch4.CollectionInjection">
    <property name="map">
        <map>
            <entry key="someValue">
                <value>Hello World!</value>
            </entry>
            <entry key="someBean">
                <ref local="oracle"/>
            </entry>
        </map>
    </property>
    <property name="props">
        <props>
            <prop key="firstName">
                Rob
            </prop>
            <prop key="secondName">
                Harrop
            </prop>
        </props>
    </property>
    <property name="set">
        <set>
            <value>Hello World!</value>
            <ref local="oracle"/>
        </set>
    </property>
    <property name="list">
        <list>
            <value>Hello World!</value>
            <ref local="oracle"/>
        </list>
    </property>
</bean>

posted @ 2006-12-21 10:22 刘璐 阅读(584) | 评论 (0)编辑 收藏

《Pro Spring》学习笔记(3)--Spring中的IOC

 

      控制反转包括两种类型:依赖查找(Dependency Lookup)和依赖注入(Dependency Injection),我们主要讨论的是依赖注入。
      依赖注入可以分为两种类型:构造子注入(Constructor Dependency Injection)和设值注入(Setter Dependency Injection)
      构造子注入,组件的依赖关系是通过构造函数来提供的,每个依赖关系对应构造函数的各个参数,IOC容器在实例化组件时,通过构造函数注入依赖关系。
public class ConstructorInjection {
    private Dependency dep;
    public ConstructorInjection(Dependency dep) {
        this.dep = dep;
    }
}
构造子注入适用于在使用某个组件之前,确保所有的依赖关系都已注入。
      设值注入,组件的依赖关系是通过JavaBean形式的setter方法注入的,IOC容器通过调用相应的set方法注入依赖关系。
public class SetterInjection {
    private Dependency dep;
    public void setMyDependency(Dependency dep) {
        this.dep = dep;
    }
}
设值注入适用于需要给某些依赖关系提供默认值的情况。
      Spring IOC容器的核心是BeanFactory,BeanFactory负责管理组件以及组件间的依赖关系。术语bean在Spring中代表由容器管理的任何组件。Spring提供了两种常用的BeanFactory实现:DefaultListableBeanFactory和XmlBeanFactory。
      在BeanFactory中,每个bean都至少有一个名称,作为唯一标识,如果bean拥有多个名称的话,那么除第一个名称外的其它名称都将被认为是别名。
      DefaultListableBeanFactory可以使用PropertiesBeanDefinitionReader或者XmlBeanDefinitionReader(当然还可以是其它任何实现了BeanDefinitionReader接口的Bean定义读取器)来读取配置文件。
//使用PropertiesBeanDefinitionReader
private static BeanFactory getBeanFactory() throws Exception {
    // get the bean factory
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    // create a definition reader
    PropertiesBeanDefinitionReader rdr = new PropertiesBeanDefinitionReader(factory);
    // load the configuration options
   
Properties props = new Properties();
    props.load(new FileInputStream("./ch2/src/conf/beans.properties"));
    rdr.registerBeanDefinitions(props);
    return factory;
}
//使用XmlBeanDefinitionReader
private static BeanFactory getBeanFactory() throws Exception {
    // get the bean factory
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    // create a definition reader
    XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory);
    // load the configuration options
    rdr.loadBeanDefinitions(new FileSystemResource("ch4/src/conf/beans.xml"));
    return factory;
}
      XmlBeanFactory继承了DefaultListableBeanFactory,在使用XML配置文件时可以简化代码的编写,这也是我们最常用的BeanFactory。
private static BeanFactory getBeanFactory() throws Exception {
    XmlBeanFactory factory =
        new XmlBeanFactory(new FileSystemResource("ch4/src/conf/beans.xml"));
    return factory;
}
      获得了BeanFactory对象后,我们就可以使用bean的名称来获取我们需要的组件对象了。
Oracle oracle = (Oracle)factoyr.get("oracle");

posted @ 2006-12-21 10:20 刘璐 阅读(310) | 评论 (0)编辑 收藏

《Pro Spring》学习笔记(2)--何为Spring

 

      Spring通常被称为是构造Java工程的轻量级框架。这其中包含了两方面的内容:首先,你可以使用Spring构造各种Java工程,而不是像Apache的Struts那样,仅仅局限于Web工程。其次,所谓轻量级框架,并不是指类的数量或是工程的规模是轻量级的,用Spring的话说,轻量级就意味着更少的影响,你可以很容易的修改你的程序来获得Spring提供的各种好处,也可以很容易的从你的工程中去除Spring。当然,需要注意的是,这仅仅是指Spring的核心组件。Spring还提供了很多其它的组件,像数据访问等,使用这些组件,将使得你的工程与Spring框架形成耦合,但是,相比于你获得的好处而言,这些耦合根本算不得什么。
      Spring框架的核心是基于控制反转(Invdersion Of Control, IOC)理论的,控制反转使得我们可以在外部来创建和管理组件之间的依赖关系。例如:类Foo依赖于一个Bar类型的实例来执行某些操作,传统的方式是,Foo使用new关键字或者从某个工厂类来创建一个Bar类的实例。然而,使用控制反转,一个Bar类型的实例将在运行时由外部程序提供。这种方式可以很形象的看作是在运行时,将依赖的组件实例注入到当前组件中。因此,在某些时候,控制反转也被称为依赖注入(Dependency Injection, DI)。在Spring中,你可以认为控制反转就等同于依赖注入。
      依赖注入给我们带来的好处包括:
      1.减少了组件关联的代码:你不再需要在组件内部自己创建需要使用的其它组件,它们会在运行时自动被注入进来,特别是当某些组件需要通过JNDI来获得,或是根本无法直接获得,例如远程资源时,DI带来的好处就更加明显了。
      2.将依赖关系移到代码外:这会带来两点好处,首先,你可以在外部方便的管理组件间的依赖关系,而不需要重新编译代码。其次,你可以方便的切换某些依赖的实现类,例如将PostgreSQL的DAO实现切换为Oracle的DAO实现。
      3.统一的依赖管理:传统的散布在工程各处的管理依赖关系的代码将不复存在,所有的依赖信息都集中在一个统一的地方,这使得维护变得容易,同时降低了发生错误的可能。
      4.提高了可测试性:你可以很容易的替换依赖类的实现方式,如使用mock实现来代替真正的实现方式。假设我们需要测试业务对象(Business Object, BO),我们就可以使用mock实现来代替真正的DAO实现,从而避免真正地访问数据库,这大大提高了测试的效率。
      5.遵循良好的设计方式:使用DI通常意味着遵循面向接口的设计方式。毫无疑问,面向接口是一种良好的设计方式。
      Spring框架还包括了以下这些方面的内容:
      1.面向方面的编程(Aspect Oriented Programming, AOP)
      2.数据访问(Accessing Data in Spring)
      3.事务管理(Managing Transactions)
      4.简化J2EE的整合(Simplifying and Integrating with J2EE)
      5.Web层的MVC框架(MVC in the Web Tier)
      6.对远程访问的支持(Remoting Support)
      7.邮件支持(Mail Support)
      8.任务安排的支持(Job Scheduling Support)
      9.简化的异常处理(Simplified Exception Handling)
      10.源代码级的元数据(Source Level Metadata)

posted @ 2006-12-21 10:20 刘璐 阅读(345) | 评论 (0)编辑 收藏

仅列出标题
共7页: 上一页 1 2 3 4 5 6 7 下一页