Spring Framework 官方文档——核心技术


未完结,请稍后再看

版本:5.1.11.BUILD-SNAPSHOT

参考文档的这一部分涵盖了Spring框架的所有不可或缺的技术。

Spring框架中最重要的就是控制反转(IoC)容器。介绍完IoC容器以后,接下来将全面介绍Spring的面向切面编程(AOP)技术。Spring框架有自己的AOP框架,该框架概念简单,并且八成的企业级AOP需求都能满足。

Spring框架还提供了与AspectJ框架的集成。AspectJ的功能是目前最丰富的——当然,它也是Java企业领域最成熟的AOP实现。

IoC容器

本章介绍了Spring的控制反转(IoC)容器。

Ioc容器和Bean简介

本章介绍了Spring框架对控制反转(IoC)思想的实现。IoC亦称作依赖注入(DI)。在控制反转的过程中,对象仅通过构造函数参数、工厂方法参数或者对象实例上设置的属性来定义其依赖项。[译者注:有点绕呵,看不懂先接着往下看一看吧~] 然后,容器在创建Bean时注入哪些依赖项。这个过程与Bean自己控制依赖的实例化和定位的过程相反,因此称之为控制反转。

org.springframework.beans org.springframework.context 包是Spring框架中IoC容器的基础。BeanFactory接口提供了高级的配置机制来管理任意类型的对象。ApplicationContextBeanFactory的子接口,它做了如下增强:

  • 与Spring的AOP特性集成更容易。
  • 消息资源处理(用于国际化)。
  • 特定的应用层上下文,例如:WebApplicationContext用于WEB应用。

简而言之,BeanFactory提供了配置框架和基础功能,ApplicationContext则增加了更多的企业级功能。ApplicationContextBeanFactory的完超集,在本章中描述的Spring的IoC容器都是指它。有关使用BeanFactory而不是ApplicationContext的信息,请参见有关BeanFactory的章节。

在Spring中,构成应用程序主干并且由Spring IoC容器管理的对象称为Bean。Bean是由Spring IoC容器实例化、组装和管理的对象。除此以外,Bean仅仅是应用程序中众多对象之一,Bean及其之间的依赖关系反隐在容器使用的配置元数据中。

容器概览

org.springframework.context.ApplicationContext接口代表了Spring的IoC容器,它负责实例化、配置和组装Bean。容器通过读取配置元数据来获取将要实例化、配置、组装的对象的说明。配置元数据的表现形式有XML、Java注解或Java代码。通过他们,你可以表达出哪些组成你的应用程序的对象以及他们之间丰富的依赖关系。

Spring内置了几种ApplicationContext的实现。在独立的应用程序中,通常创建ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext。XML是传统的配置元数据定义格式,你还可以通过提供少量的XML配置来声明弃用对其他元数据格式的支持,然后指示容器将Java注释或者代码作为元数据格式。

在大多数应用场景中,不需要显式的用户代码即可实例化一个或多个Spring IoC容器。例如,在Web应用场景中,只需要web.xml中的八行样板代码就够了。如果使用 Spring Tool Suite(基于Eclipse的开发环境),则只需单击几次鼠标或按几次键盘即可轻松创建此样板配置。

下图显示了Spring的工作原理的高级视图。由于你的应用程序类与配置元数据结合在一起,因此,在ApplicationContext创建和初始化以后你将拥有一个完全配置且可执行的系统或应用程序。

配置元数据

如上图所示,Spring IoC容器使用配置元数据的形式(来描述容器)。这个配置元数据表示你作为应用程序开发者,告诉Spring容器该如何实例化、配置以及组装对象。

XML是提供配置元数据的典型形式,本章我们将使用这种形式来阐述Spring IoC容器的关键概念和特性。

配置元数据并不限于XML形式。Spring IoC容器和配置元数据的格式之间是松耦合的。现下,更多的开发者选择使用基于Java代码的配置形式。

有关在Spring容器中使用其他形式的配置元数据的信息,请参见:

  • 基于注释的配置:Spring 2.5引入了对基于注释的配置元数据的支持。
  • 基于Java的配置:从Spring 3.0开始,Spring JavaConfig项目提供的许多功能成为核心Spring框架的一部分。因此,您可以使用Java而不是XML文件来定义应用程序类外部的bean。要使用这些新功能,请参阅 @Configuration@Bean@Import,和@DependsOn注释。

译者注:上述的几个URL连接的是英文的文档,请知悉。我认为跳跃式地看文档并不是一个好的习惯,后续章节中,有些原文档中存在的连接可能会被取消,望知悉。后不再赘述。

Spring应用中至少包含一个由容器管理的Bean。使用XML配置时,通常在顶<beans/> 节点内插入<bean/> 节点,<bean/> 节点对应了程序中的Bean。基于Java的配置通常在由@Configuration 标记的类中使用@Bean注解来标记方法,被标记的方法的返回值就是Bean。

Bean定义和组成应用程序的对象一一对应。通常,你会定义服务层对象、数据访问层对象(DAO)、表现层对象(例如Struts的实例)、基础设施对象(例如HibernateSessionFactories,JMS Queues等 )。我们通常不会在容器中配置实体对象,因为这是DAO层和业务逻辑的职责。不过,你可以通过将Spring与Aspec集成起来,来配置一些在IoC容器外部创建的对象。详情请参见:通过AspectJ在Spring中注入实体对象。

下面的例子展示了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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="..." class="..."> ① ②
        <!-- collaborators and configuration for this bean go here -->
    </bean>
    
    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>
    
    <!-- more bean definitions go here -->
    
</beans>

id属性是标识Bean定义的字符串。

class属性定义了Bean的类型,它的值是类的全限定名。

id属性的值可以被协作对象引用。本例中没有展示协作Bean引用依赖Bea更多信息请看依赖注入章节。

实例化容器

ApplicationContext类的构造函数的路径参数是配置元数据的资源文件路径,容器根据这些资源路径去加载各种外部资源,这些 资源路径可能是本地文件系统路径、Java类路径等。

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

在了解了Spring的IoC容器以后,你可能会想了解更多有关Spring中资源的抽象。资源提供了一种方便的机制来从采用URI语法定义的位置读取输入流。具体而言,资源路径用来描述应用程序上下文(正如应用程序上下文和资源路径章节中描述的那样)。

下面的例子展示了服务层对象的配置文件(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
        https://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"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for services go here -->

</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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for data access objects go here -->

</beans>

在上面的例子中,服务层由PetStoreServiceImpl 类和两个数据存取层对象(分别为JpaAccountDaoJpaItemDao类对象)组成。property元素的name属性是指JavaBean属性的名称,ref属性则是另一个Bean定义的ididref之间的联系,表达了协作对象之间的依赖关系。有关对象依赖注入的配置的更多信息,请参见依赖注入章节。

组织基于XML的配置元数据

将Bean定义分散在多个XML文件中可能会很有用。通常,每个单独的XML配置文件都代表体系结构中的逻辑层或模块。

你可以使用应用程序上下文的构造器来从这些XML片段中加载Bean定义,正如前一章节看到的那样,应用程序上下文容器的构造函数可以加载多个资源路径。或者,我们可以使用<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.xmlmessageSource.xmlthemeSource.xml 三个配置文件中加载。所有的位置路径都是相对于做导入操作的文件的位置路径,因此services.xml必须在同级目录,messageSource.xmlthemeSource.xml必须在resources目录下(resources目录和做导入操作的文件在同一层)。我们可以看到,反斜杠在这里被忽略了。但是,鉴于 这里都是使用相对路径,我们最好还是不要使用反斜杠。根据<beans/>的文件约束,导入的文件的内容必须是有效的XML Bean定义。

可以使用"../"路径来引用父目录中的文件,但是不建议这样做。如果引用了父目录,可能会造成对当前应用程序外部的文件进行依赖。特别是在classpath:URL(例如:classpath:../services.xml)这种形式下不推荐使用。这种形式在运行时选择最近的类路径根目录,然后再去寻找其父目录,在泪目镜配置更改以后,可能会导致选择了其他的错误目录。

你可以使用资源的全限定路径来代替相对路径:例如file:C:/config/services.xmlclasspath:/config/services.xml。但是,请注意你正在将应用程序耦合到特定的绝对位置。通常最好为这样的绝对位置保留一个间接寻址,例如,通过在运行时针对JVM系统属性解析的“ $ {…}”占位符。

命名空间本身提供了import指令功能。Spring提供的一系列XML名称空间(例如contextutil名称空间)中提供了超出普通bean定义的其他配置功能。

Groovy:Bean定义领域特定语言

现在举另一个外部化的配置元数据的例子:使用领域特定语言Groovy语言来表达Bean定义。Groovy语言因为Grails框架而闻名于世。通常,这些配置位于".groovy"文件中,结构如下例所示:

beans {
    dataSource(BasicDataSource) {
        driverClassName = "org.hsqldb.jdbcDriver"
        url = "jdbc:hsqldb:mem:grailsDB"
        username = "sa"
        password = ""
        settings = [mynew:"setting"]
    }
    sessionFactory(SessionFactory) {
        dataSource = dataSource
    }
    myService(MyService) {
        nestedBean = { AnotherBean bean ->
            dataSource = dataSource
        }
    }
}

这种配置样式在很大程度上等同于XML bean定义,甚至支持Spring的XML配置的命名空间。它还允许通过importBeans指令导入XML bean定义文件。

使用容器

ApplicationContext是维护Bean定义以及Bean依赖关系注册表的高级工厂的接口。通过使用方法T getBean(String name, Class<T> requiredType),你可以检索bean的实例。

下例展示了使用ApplicationContext来读取Bean定义:

// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();

使用Groovy的配置,它的引导方法看起来非常相似。他有一个不同的上下文实现类,该类可识别Groovy(但也了解XML形式的Bean定义)。以下示例显示了如何引导Groovy配置:

ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");

最灵活的变体是GenericApplicationContext 与读取器委托结合使用——例如与XmlBeanDefinitionReader 结合来读取XML文件:

GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();

你也可以使用``GroovyBeanDefinitionReader  来读取Groovy文件:

GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
context.refresh();

你可以在同一个ApplicationContext里面混用这些阅读器,这样你就可以把Bean定义配置在不同形式的资源中。

你可以使用getBean来检索Bean实例。ApplicationContext接口还有几种其他的方式来检索Bean,但是理想情况下,你永远也不要在代码里使用。事实上,你的应用程序代码根本不应该调用getBean方法,这样应用程序才完全不依赖Spring的API。例如,Spring与Web框架的集成为各种Web框架组件(例如控制器和JSF管理的Bean)提供了依赖项注入,使你可以通过元数据(例如自动装配注解)声明对特定Bean的依赖。

Bean概览


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM