码迷,mamicode.com
首页 > 编程语言 > 详细

Spring 4.x 概述

时间:2015-08-09 17:19:38      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:

1    介绍Spring容器和Beans

本文覆盖Spring框架的控制反转(IoC)原则的实现。IoC也被称为抵赖注入(DI)。这是一个定义对象依赖性的过程,即,它们处理其他对象,只通过构造函数的参数、工厂方法参数或在对象实例被构造或从工厂方法返回时设置属性。然后当容器创建bean时注入这些依赖项。这个过程从根本上是反向的,因此得名控制反转(IoC),bean自己控制实例化,或者通过直接使用类的构造函数定位它的依赖关系,或一个机制例如服务定位器模式。

org.springframework.beans和org.springframework.context包是Spring框架的IoC容器的基础。BeanFactory接口提供一个高级的配置机制管理任何类型的对象的能力。ApplicationContext是BeanFactory的子接口。它增加了容易与Spring的AOP功能集成的特性;消息资源处理(用于国际化),事件发布;和应用层特定上下文,例如在Web应用程序中使用WebApplicationContext。

总而言之,BeanFactory提供配置框架和基本功能,而ApplicationContext添加更多企业特性功能。BeanFactory是ApplicationContext的完整超集,专门用于本章描述的Spring的IoC容器。

在Spring中,你的应用程序的支柱表单对象,通过Spring IoC容器管理称为Beans。Bean是一个通过Spring IoC容器管理初始化、转配等等的对象。另外,Bean就是在你的应用程序中许多对象之一。Beans和它们之间的依赖关系,反映在一个容器所使用的配置元数据。

2    容器概述

接口org.springframework.context.ApplicationContext代表Spring IoC容器,负责初始化、配置和转配前面提及的Beans。容器通过读取配置元数据获取它的对象实例化、配置和分配指令。配置元数据以XML、Java注解或Java代码中代表。它允许你表示构成你的应用程序的对象和这些对象之间丰富的依赖关系。

Spring提供几个开箱即用的ApplicationContext接口实现。在独立的应用程序中通常创建一个ClassPathXmlApplicationContext或FileSystemXmlApplicationContext实例。虽然XML已经是定义配置元数据的传统格式,你能命令容器使用Java注解或代码作为元数据格式提供少量XML配置声明启用这些额外元数据格式。

在大多数引用环境中,显式的用户代码不需要实例化一个或多个Spring IoC容器的实例。例如,在一个Web应用环境中,一个简单的八行(左右)Web描述符XML在应用程序的web.xml文件中通常会足够了。如果你使用SpringSource Tool Suite Eclipse-powered开发环境这个样板配置可以很容易地通过点击鼠标或按键创建。

下图是Spring工作的高级视图。你的应用类结合配置元数据以便在ApplicationContext创建和初始化,你有一个完整的配置和可执行系统或应用程序。

技术分享

图1 Spring IoC容器

2.1    配制元数据

如上图所示,Spring IoC容器消耗配置元数据的一种形式;该配置元数据代表你作为一个应用程序开发者告诉Spring容器如何在你应用程序中实例化、配置和装配对象。

配置元数据传统是以简单而直观的XML格式提供,本章大多数是转达Spring IoC容器的关键概念和功能。

注意:基于XML元数据不是仅仅允许的配置元数据形式。Spring IoC容器本身的编写是完全脱离这个格式的配置元数据。这些天许多开发人员选择基于java的配置Spring应用程序。

关于Spring容器使用其它形式的元数据,见:

  • 基于注解配置:Spring 2.5引入支持注解配置元数据。

  • 基于Java配置:从Spring 3.0开始,Spring JavaConfig项目提供的许多特性成为核心Spring框架的一部分。因此,你能通过使用Java而不是XML文件定义Beans扩展你的应用类。为了使用这些新特性,见@Configuration、@Bean、@Import和@DependsOn注解。

  • Spring配置通常包括至少一个和通常容器必须管理的多个bean定义组成。基于XML配置元数据显示这些Beans配置为顶层元素<beans/>中的<bean/>元素。Java配置通常在一个@Configuration类中使用@Bean注解方法。

这些bean定义对应着你的应用程序实际的组成对象。通常你定义服务层对象、数据访问对象(DAOs)、展示对象例如Struts的Action实例、基础设施对象例如Hibernate的SessionFactories、JMS的Queues等等。通常不在容器中配置细粒度的域对象,因为它通常是DAOs和业务逻辑负责创建和加载域对象。然而,你可以使用Spring与AspectJ集成配置对象,在IoC容器之外控制创建。

下面的例子显示了基于xml的配置元数据的基本结构:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">
        <!--在这里配置该bean的依赖-->
    </bean>

    <bean id="..." class="...">
        <!--在这里配置该bean的依赖-->
    </bean>

    <!—在这里配置更多的bean定义 -->

</beans>

id属性是一个用于识别bean声明的字符串。class属性使用完全限定类名定义bean的类型。id属性的值引用合作的对象。XML引用合作对象没有显示在本例中。

2.2    实例化容器

实例化一个Spring IoC容器非常简单。位置路径提供给一个ApplicationContext构造函数,实际上是允许容器从各种各样的本地文件系统等外部资源,从Java的CLASSPATH等等加载配置元数据资源字符串。

ApplicationContext context = new ClassPathXmlApplicationContext(

      new String[] {"services.xml", "daos.xml"});

下面的例子展示服务层对象(services.xml)配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- services -->

    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="itemDao" ref="itemDao"/>
        <!--在这里配置该bean的依赖-->
    </bean>

    <!—在这里配置更多的service bean -->

</beans>

下面的例子展示数据访问对象daos.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!--在这里配置该bean的依赖-->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!--在这里配置该bean的依赖-->
    </bean>

    <!—在这里配置更多的数据访问对象-->

</beans>

在前面的例子中,服务层由PetStoreServiceImpl类和两个类型是JpaAccountDao和JpaItemDao(基于JPA对象/关系映射标准)的数据访问对象的组成。property name元素引用JavaBean的属性名称,而ref元素引用另一个Bean定义。这个id和ref元素之间的联系表达合作对象之间的依赖关系。

基于XML组装配制元数据

它可用于跨越多个XML文件定义Bean。通常每个单独的XML配置文件在你的体系结构中代表一个逻辑层或模块。

你能使用应用程序的上下文构造函数从所有XML片段中加载Bean定义。该构造函数需要多个Resource位置,就像上一节所示。或者,使用一个或多个<import/>元素从另一个文件中加载Bean定义。例如:

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

在之前的例子中,从三个文件加载外部bean定义:services.xml、messageSource.xml和themeSource.xml。所有的位置路径相对于定义导入的文件,因此services.xml必须在相同的目录或类路径作为文件导入,然而messageSource.xml和themeSource.xml必须在resources位置下导入文件。正如你所看见的,最前面的斜杠被忽略,但是鉴于这些路径是相对的,最好不要使用斜杠。被导入的文件内容,包括在顶层<beans/>元素中,必须是根据Spring Schema有效的XML bean定义。

注意:在父目录使用一个相对”../”路径的文件是可能的,但是不推荐。这样会创建一个依赖文件不在当前的应用程序。特别是,不推荐这个引用“classpath:“url(例如,“classpath:../services.xml”),运行时解决过程选择“最近的”classpath根然后进入它的父目录。类路径配置更改可能会导致一个不正确的目录。

你可以使用完全限定的资源的位置,而不是相对路径:例如,”file:C:/config/services.xml”或”classpath:/config/services.xml”。然而,请注意,你是耦合应用程序的配置特定的绝对位置。一般保持一个间接的绝对位置,例如,通过”${...}”占位符在运行时对JVM系统属性进行解析。

2.3    使用容器

ApplicationContext是一个能维护不同Bean和它们的依赖关系的注册表的高级工程的接口。使用方法T getBean(String name, Class<T> requiredType),你能检索你的Beans实例。

ApplicationContext使你能读取Bean定义和访问它们:

// 创建并配置beans
ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

// 检索配置实例
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// 使用配置实例
List<String> userList = service.getUsernameList();

你使用getBean()检索你的Bean实例。ApplicationContext接口有一些其它的方法检索Bean,但理想情况下,你的应用程序代码应该从不使用它们。的确,你的应用程序代码应该不调用所有的getBean()方法,从而不依赖于Spring APIs。例如,Spring与Web框架的集成提供依赖注入各种Web框架类,例如,控制器和JSF-管理Bean。

3    Bean概述

Spring IoC容器管理一个或多个Bean。这些Bean使用你提供给容器的配置元数据创建,例如,以XML <bean/> 形式定义。容器本身将这些Bean定义作为BeanDefinition对象,包含(以及其它信息)以下元数据:

  • 包完全限定类名:通常是定义Bean的实际实现类。

  • Bean行为配置元素,不同状态Bean在容器中的行为(scope、lifecycle、callbacks等等)。

  • 引用相关Bean;这些引用也称合作者或依赖。

  • 其它配置设置用于设置新创建的对象,例如,用于在Bean中管理连接池的连接数,或连接池限制大小。

该元数据转换为一组组成每个bean定义的属性。

表 1 Bean定义

class

name

scope

constructor arguments

properties

autowiring mode

lazy-initialization mode

initialization method

destruction method


除了包含如何创建特定Bean的Bean定义,ApplicationContext实现也允许注册创建在容器之外的已存在的对象。通过访问ApplicationContext的getBeanFactory()访问BeanFactory,返回BeanFactory实现DefaultListableBeanFactory。DefaultListableBeanFactory支持通过方法registerSingleton(..)和registerBeanDefinition(..)注册。然而,典型应用程序通过元数据Bean定义处理单独Bean定义。

3.1    命名Bean

每个Bean有一个或多个标识符。这些标识符在托管Bean的容器中必须唯一。一个Bean通常只有一个标识符,但是如果他需要更多标识符,可以考虑额外的别名。

在基于XML配置元数据中,你能使用id和/或name属性指定Bean标识符。id属性允许你指定唯一一个id。按照惯例这些名称是字符数字(myBean、fooService等等),但也可以包含特殊字符。如果你想引入其它Bean的别名,你也能在name属性中指定它们,通过逗号(,),分号(;)或空格分隔。作为一个历史的注意,在Spring3.1之前的版本,id属性作为xsd:ID类型定义,可能限制字符。直到3.1,它定义为xsd:string类型。注意,Bean id在容器中独一无二,不再通过XML解析。

你不必为Bean提供名称或id。如果没有显示的提供名称或id,容器为Bean生成一个唯一名称。然而,如果你想要通过名称应用Bean,通过使用ref元素或Service Locator风格查找,你必须提供一个名称。不提供名称的动机与使用内部bean和自动转配合作者有关。

Bean命名规范

命名Bean的规范类似于Java命名实例字段的标准。即,Bean名称开始于一个小写字母的驼峰式命名。例如:’accountManager’、’accountService’、’userDao’、’loginController’等等。

命名Bean规范使你的配置容易阅读理解,如果你使用Spring AOP,当应用通知到一组相关名称的bean上时它帮助很大。

bean定义外使用bean别名

在Bean定义中,你能为Bean提供更多名称,通过结合使用id属性指定的一个名字,和在name属性指定任意数量的其它名称。这些名称相当于同一个Bean的别名,在某些情况下有用,例如,允许应用程序中的每个组件引用一个共同依赖通过使用特定组件本身的bean名称。

然而,指定所有别名定义的bean实际上是并不总是足够。它有时需要引入一个别名的bean定义。通常这样的大型系统中配置划分在每个子系统,每个子系统都有自己的一组对象定义。在基于XML配置元数据中,你能使用<alias/>元素完成这个。

<alias name="fromName" alias="toName"/>

在这种情况下,Bean在相同的容器中名为fromName,也可以使用别名定义后引用为toName。

例如,子系统A的配置元数据可以通过subsystemA-dataSource引用DataSource。子系统B的配置元数据可以通过subsystemB-dataSource引用DataSource。当组成主应用程序使用这些子系统主应用通过名为myApp-dataSource引用DataSource时。所有三个名字引用同一个对象添加到MyApp配置以下别名定义元数据:

<alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/>
<alias name="subsystemA-dataSource" alias="myApp-dataSource" />

现在每个组件和主应用程序可以通过唯一名称引用数据源,保证不与其它任何定义冲突(有效的创建一个命名空间),然而,他们引用相同bean。

Java配置

如果你使用Java配置,@Bean注解能用于提供别名。

3.2    实例化Beans

一个bean的定义基本上是创建一个或多个对象的秘诀。当容器被询问时,容器查找一个命名Bean的秘诀,并使用封装配置元数据的bean定义来创建(或获得)一个实际对象。

如果你使用基于XML的配置元数据,你要在<bean/>元素的class属性中指定对象的类型(或class)。该class属性在BeanDefinition实例中是一个Class属性,通常是必选的。你有两种方式使用Class属性:

  • 典型的,在构建情况下指定Bean类,容器直接通过反射调用它的构造函数创建Bean,有点像Java代码使用new操作符。

  • 指定实际的类包含静态工厂方法,将调用创建对象,不常见的情况下,容器在一个类上调用一个静态工厂方法创建bean。调用静态工厂方法可以返回完全相同的类或另一个类的对象类型。

内部类名称。如果你想要配置一个静态嵌套类的bean定义,你必须使用嵌套类的二进制类名。
例如,如果你有一个类Foo在com.example包中,并且Foo类有一个静态嵌套类Bar,那么bean定义上的class属性可能是:
com.example.Foo$Bar
注意,在名称上使用$字符分隔嵌套类和外部类名称。

使用构造函数实例化

当你通过构造函数创建一个Bean时,所有普通类都可用和兼容Spring。即,被开发的类不需要实现任何特定的接口或以特定的方式进行编码。简单的指定bean class即可。然而,依赖于你使用什么样的IoC指定Bean,你可能需要一个默认(无参)构造函数。

Spring IoC容器可以管理几乎任何你想要管理的类;它并不局限于管理真正的JavaBean。大多数Spring用户更喜欢实际JavaBean只有一个默认(无参)构造函数和适当的setter和getter方法建模后的属性容器。你也可以在你的容器中管理非Bean式的类。例如,如果你需要使用遗留的绝对不遵循JavaBean规范的连接池,Spring也能管理它。

使用基于XML配置元数据你能指定你的Bean类:

<bean id="exampleBean" class="examples.ExampleBean"/>

<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

使用静态工厂方法实例化

当你定义一个Bean使用一个静态工厂方法创建时,你使用class属性指定包含静态工厂方法的类,一个名为factory-method的属性指定工厂方法的名称。你应该能够调用该方法(使用可选参数),返回一个对象,随后被看作是通过创建一个构造函数。我们在遗留代码中使用这么一个bean定义调用静态工厂。

下面的bean定义指定bean将通过调用factory-method创建的。定义并没有指定返回对象的类型(类),只包含工厂方法的类。在该例子中,createInstance()方法必须是static方法。

<bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>

public class ClientService {
    private static ClientService clientService = new ClientService();
    private ClientService() {}

    public static ClientService createInstance() {
        return clientService;
    }
}

类似于一个静态工厂方法初始化,使用一个实例工厂方法调用一个已存在bean的非静态的方法从构造函数创建一个新bean。使用这种机制,保持class属性为空,在factory-bean属性中,指定在当前(父/祖先)容器中包含调用实例方法创建对象的bean的属性名。使用factory-method属性设置工厂方法的名称。

<!—工厂bean,包含一个createInstance()方法-->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!—注入任意依赖-->
</bean>

<!—通过工厂bean创建的bean -->
<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>

public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();
    private DefaultServiceLocator() {}

    public ClientService createClientServiceInstance() {
        return clientService;
    }
}

一个工厂类也能有多个工厂方法:

<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!--注入任意依赖-->
</bean>

<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>

<bean id="accountService"
    factory-bean="serviceLocator"
factory-method="createAccountServiceInstance"/>

public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();
    private static AccountService accountService = new AccountServiceImpl();

    private DefaultServiceLocator() {}

    public ClientService createClientServiceInstance() {
        return clientService;
    }

    public AccountService createAccountServiceInstance() {
        return accountService;
    }

}

这种方法表明,工厂bean本身可以通过依赖注入(DI)管理和配置。

注意:在Spring文档中,工厂bean在Spring容器中引用bean配置,将通过一个实例或静态工厂方法创建对象。相比之下,FactoryBean(请注意大小写)引用Spring特定FactoryBean。



Spring 4.x 概述

标签:

原文地址:http://my.oschina.net/u/2000201/blog/489779

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!