spring再学习

可以但不建议使用相对“…/”路径引用父目录中的文件。这样做会创建对当前应用程序之外的文件的依赖。特别是,不建议将此引用用于类路径: URL(例如,类路径:…/services.xml),其中运行时解析过程选择“最近的”类路径根,然后查看其父目录。类路径配置更改可能会导致选择不同的、不正确的目录。
您始终可以使用完全限定的资源位置而不是相对路径:例如,文件:C:/config/services.xml 或类路径:/config/services.xml。但是,请注意您将应用程序的配置耦合到特定的绝对路径位置。通常最好为这种绝对位置保留一个间接地址——例如,通过在运行时根据 JVM 系统属性解析的“${…}”占位符。

上述这段话我理解担忧不完全理解,不建议使用父目录级别的相对路径,推荐使用绝对路径,但是不应该绝对路径不才是容易改变的吗?而相对路径才是不容易改变的吗?希望能有高手谈一谈。

Spring Framework

1.1. Introduction to the Spring IoC Container and Beans
其中最重要的是Spring Framework的控制反转(InversionofControl,IoC)容器。在对Spring Framework的IoC容器进行全面介绍之后,将全面介绍Spring的面向切面编程(AOP)技术。Spring Framework有自己的AOP框架,在概念上很容易理解,它成功地解决了Java企业编程中80%的AOP需求。

org.springframework.beans 和 org.springframework.context 包是 Spring Framework 的 IoC 容器的基础。BeanFactory 接口提供了一种能够管理任何类型对象的高级配置机制。ApplicationContext 是 BeanFactory 的子接口。

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

简而言之,BeanFactory 提供了配置框架和基本功能,ApplicationContext 增加了更多企业特有的功能。ApplicationContext 是 BeanFactory 的完整超集,在本章描述 Spring 的 IoC 容器时独占使用。使用 BeanFactory 而不是 ApplicationContext,请参阅 BeanFactory。

在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。bean 是由 Spring IoC 容器实例化、组装和管理的对象。否则,bean 只是简单的Bean 以及它们之间的依赖关系反映在容器使用的配置元数据中。

1.2. Container Overview

org.springframework.context.ApplicationContext 接口代表 Spring IoC 容器,负责实例化、配置和组装 bean。容器通过读取配置元数据来获取关于实例化、配置和组装哪些对象的指令。它让你表达组成应用程序的对象以及这些对象之间丰富的相互依赖关系。

Spring 提供了 ApplicationContext 接口的几种实现。在独立应用程序中,通常创建 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext 的实例。虽然 XML 是定义配置元数据的传统格式,但您可以指示容器使用 Java 注释或通过提供少量 XML 配置来声明性地启用对这些附加元数据格式的支持,将其编码为元数据格式。

在大多数应用场景中,不需要显式的用户代码来实例化一个或多个Spring IoC容器的实例,例如在web应用场景中,web.xml中简单的八行(左右)样板web描述符XML应用程序的文件通常就足够了(请参阅Web 应用程序的便捷 ApplicationContext 实例化)。如果您使用 Spring Tools for Eclipse(一个 Eclipse 驱动的开发环境),您可以通过点击几下鼠标或按键轻松创建这个样板配置。

下图显示了 Spring 工作原理的高级视图。您的应用程序类与配置元数据相结合,因此在 ApplicationContext 被创建和初始化之后,您就有了一个完全配置且可执行的系统或应用程序。(配置元数据:个人理解说的就是xml或其他的配置信息)

spring machine文档 spring官方文档看不懂_java

1.2.1. 配置元数据

如上图所示,Spring IoC 容器使用一种形式的配置元数据。该配置元数据表示您作为应用程序开发人员如何告诉 Spring 容器实例化、配置和组装应用程序中的对象。

配置元数据传统上以简单直观的 XML 格式提供,本章的大部分内容使用这种格式来传达 Spring IoC 容器的关键概念和特性。

基于XML的元数据不是唯一允许的配置元数据形式。SpringIOC容器本身与实际写入此配置元数据的格式完全解耦。现在,许多开发人员为他们的Spring应用程序选择基于Java的配置。(高亮显示)

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

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

Spring 配置至少包含一个必须由容器管理的 bean 定义,通常是多个 bean 定义。基于 XML 的配置元数据将这些 bean 配置为顶级 元素内的 元素。Java 配置通常使用 @ @Configuration 类中的 Bean 注释方法。

这些bean定义对应于构成应用程序的实际对象。通常,在容器配置中您定义服务层对象、数据访问对象(DAO)、表示对象(如Struts操作实例)、基础结构对象(如Hibernate SessionFactorys)、JMS队列等。通常,不在容器中配置细粒度域对象,因为创建和加载域对象通常是DAO和业务逻辑的责任。但是,您可以使用Spring与AspectJ的集成来配置在IoC容器控制之外创建的对象。请参阅使用AspectJ使用Spring注入依赖项域对象。

域对象:就是一个包含了一些属性的类,如:

Class User{
		private String name;
		private int age;
		/*
			get(),
			set();
		*/
}

以下示例显示了基于 XML 的配置元数据的基本结构:
此示例中未显示用于引用协作对象的 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 的类型并使用了完全限定的Class名称。(全限定类名:就是类名全称,带包路径的用点隔开,例如: java.lang.String。即全限定名 = 包名+类型)

1.2.2. Instantiating a Container

提供给 ApplicationContext 构造函数的一个或多个位置路径是资源字符串,它允许容器从各种外部资源(例如本地文件系统、Java CLASSPATH 等)加载配置元数据。

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

在了解了 Spring 的 IoC 容器之后,您可能想了解更多关于 Spring 的 Resource abstraction (如参考资料中所述),它提供了一种从 URI 语法中定义的位置读取 InputStream 的便捷机制。特别是,Resource 路径用于构建应用程序上下文,如应用程序上下文和资源路径中所述。

以下示例显示了服务层对象 (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类和JpaAccountDao和JpaItemDao这两个数据访问对象(基于JPA Object-Relational Mapping标准)组成,property name元素指的是JavaBean属性的名称, id 和 ref 元素之间的这种联系表达了协作对象之间的依赖关系。有关配置对象依赖关系的详细信息,请参阅依赖关系。

编写基于 XML 的配置元数据
使 bean 定义跨越多个 XML 文件会很有用。通常,每个单独的 XML 配置文件代表架构中的一个逻辑层或模块。
您可以使用application context constructor从所有这些 XML 片段加载 bean 定义。此构造函数采用多个资源位置,如上一节所示。或者,使用一个或多个 <import/> 元素来加载 bean 定义. 来自另一个或多个文件。以下示例显示了如何执行此操作(注意三个resource的值):

<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必须在同一个目录下(相对于当前xml文件)或 classpath 位置作为执行导入的文件,而 messageSource.xml 和 themeSource.xml 必须位于当前xml文件所在位置下的resources文件中。如您所见,前导斜杠(/)被忽略。但是,鉴于这些路径是相对而言,最好根本不使用斜杠。根据 Spring Schema,被导入文件的内容,包括顶级 元素,必须是有效的 XML bean 定义。

可以但不建议使用相对“…/”路径引用父目录中的文件。这样做会创建对当前应用程序之外的文件的依赖。特别是,不建议将此引用用于类路径: URL(例如,类路径:…/services.xml),其中运行时解析过程选择“最近的”类路径根,然后查看其父目录。类路径配置更改可能会导致选择不同的、不正确的目录。
您始终可以使用完全限定的资源位置而不是相对路径:例如,文件:C:/config/services.xml 或类路径:/config/services.xml。但是,请注意您将应用程序的配置耦合到特定的绝对路径位置。通常最好为这种绝对位置保留一个间接地址——例如,通过在运行时根据 JVM 系统属性解析的“${…}”占位符。

上述这段话我理解担忧不完全理解,不建议使用父目录级别的相对路径,推荐使用绝对路径,但是不应该绝对路径不才是容易改变的吗?而相对路径才是不容易改变的吗?

其他有趣的Bean定义方式
作为外部化配置元数据的另一个示例,bean 定义也可以在 Spring 的 Groovy Bean Definition DSL 中表达,如 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 定义文件。

1.2.3. 使用 Container
ApplicationContext 是高级工厂的接口,能够维护不同 bean 及其依赖项的注册表。 通过使用方法 T getBean(String name, Class 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 定义(意思是也可以用来解析xml(未验证)))。 以下示例显示了 Groovy 配置:

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

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

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

您还可以对 Groovy 文件使用 GroovyBeanDefinitionReader,如以下示例所示:

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 的依赖。

1.3. Bean 概述

Spring IoC 容器管理一个或多个 bean。 这些 bean 是使用您提供给容器的配置元数据创建的(例如,以 XML<bean/> 定义的形式)。
在容器本身内,这些 bean 定义表示为 BeanDefinition 对象,其中包含(除其他信息外)以下元数据:

  • 包限定的类名:通常是定义的 bean 的实际实现类。
  • Bean 行为配置元素,它说明 Bean 在容器中的行为方式(范围、生命周期回调等)。
  • 对 bean 执行其工作所需的其他 bean 的引用。 这些引用也称为协作者或依赖项。
  • 要在新创建的对象中设置的其他配置设置 — 例如,池的大小限制或在管理连接池的 bean 中使用的连接数。

此元数据转换为组成每个 bean 定义的一组属性。 下表描述了这些属性:

Property

Explained in…

Class

Instantiating Beans

Name

Naming Beans

Scope

Bean Scopes

Constructor arguments

Dependency Injection

Properties

Dependency Injection

Autowiring mode

Autowiring Collaborators

Lazy initialization mode

Lazy-initialized Beans

Lazy initialization mode

Lazy-initialized Beans

Initialization method

Initialization Callbacks

Destruction method

Destruction Callbacks

除了包含有关如何创建特定 bean 的信息的 bean 定义之外,ApplicationContext 实现还允许注册在容器外部(由用户)创建的现有对象。 这是通过 getBeanFactory() 方法访问 ApplicationContext 的 BeanFactory 来完成的,该方法返回 BeanFactory DefaultListableBeanFactory 实现。 DefaultListableBeanFactory 通过 registerSingleton(…) 和 registerBeanDefinition(…) 方法支持这种注册。 但是,典型的应用程序仅使用通过常规 bean 定义元数据定义的 bean。(不通过配置文件注册Bean)

Bean 元数据和手动提供的单例实例需要尽早注册,以便容器在自动装配和其他内省步骤中正确推理它们。 虽然在某种程度上支持覆盖现有元数据和现有单例实例,但官方不支持在运行时注册新 bean(与实时访问工厂同时)并可能导致并发访问异常、bean 容器中的状态不一致,或两者兼而有之。(这说明Spring中所有的Bean都应该在程序开始之初注册完成)

1.3.1. Naming Beans

每个 bean 都有一个或多个标识符。 这些标识符在承载 bean 的容器中必须是唯一的。 一个 bean 通常只有一个标识符。 但是,如果它需要多个,则可以将多余的视为别名。

在基于 XML 的配置元数据中,您可以使用 id 属性、name 属性或两者来指定 bean 标识符。 id 属性允许您指定一个 id。 通常,这些名称是字母数字(‘myBean’、‘someService’ 等),但它们也可包含特殊字符。 如果要为 bean 引入其他别名,也可以在 name 属性中指定它们,用逗号 (,)、分号 ( ; ) 或空格分隔。 作为历史记录,在 Spring 3.1 之前的版本中,id 属性被定义为 xsd:ID 类型,它限制了可能的字符。 从 3.1 开始,它被定义为 xsd:string 类型。 请注意,bean id 唯一性仍由容器强制执行,但不再由 XML 解析器强制执行。

您不需要为 bean 提供名称或 ID。 如果您没有明确提供名称或 id,容器将为该 bean 生成一个唯一的名称。 但是,如果要通过名称引用该 bean,通过使用 ref 元素或服务定位器样式查找,则必须提供名称。 不提供名称的动机与使用内部 bean 和自动装配协作者有关。

Bean 命名约定
约定是在命名 bean 时对实例字段名称使用标准 Java 约定。 也就是说,bean 名称以小写字母开头,并从那里开始使用驼峰式大小写。 此类名称的示例包括 accountManager、accountService、userDao、loginController 等。

始终如一地命名 bean 使您的配置更易于阅读和理解。 此外,如果您使用 Spring AOP,则在将建议应用于一组按名称相关的 bean 时会很有帮助。

通过类路径中的组件扫描,Spring 为未命名的组件生成 bean 名称,遵循前面描述的规则:本质上,采用简单的类名并将其初始字符转换为小写。 但是,在有多个字符且第一个和第二个字符都是大写的(不寻常的)特殊情况下,原始大小写被保留。 这些规则与 java.beans.Introspector.decapitalize(Spring 在这里使用的)定义的规则相同。

在 Bean 定义之外给 Bean 取别名
在 bean 定义本身中,您可以为 bean 提供多个名称,方法是使用 id 属性指定的最多一个名称和 name 属性中任意数量的其他名称的组合。 这些名称可以是同一个 bean 的等效别名,并且在某些情况下很有用,例如让应用程序中的每个组件通过使用特定于该组件本身的 bean 名称来引用公共依赖项。

然而,在实际定义 bean 的地方指定所有别名并不总是足够的。 有时需要为在别处定义的 bean 引入别名。 这在大型系统中很常见,其中配置在每个子系统之间拆分,每个子系统都有自己的一组对象定义。 在基于 XML 的配置元数据中,您可以使用 元素来完成此操作。 以下示例显示了如何执行此操作:

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

在这个例子,一个名为 fromName 的 bean(在同一个容器中)在使用这个别名定义之后,也可以被称为 toName。

例如,子系统 A 的配置元数据可以通过子系统 A-数据源的名称来引用数据源。 子系统 B 的配置元数据可以通过子系统 B-数据源的名称来引用数据源。 在组合使用这两个子系统的主应用程序时,主应用程序通过名称 myApp-dataSource 引用 DataSource。 要让所有三个名称都引用同一个对象,您可以将以下别名定义添加到配置元数据中:

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

用以区分不同系统对同意依赖项的引用
现在,每个组件和主应用程序都可以通过一个唯一的名称来引用 dataSource,并且保证不会与任何其他定义发生冲突(有效地创建一个命名空间),但它们引用的是同一个 bean。

如果使用 Javaconfiguration,则可以使用 @Bean 批注来提供别名。 有关详细信息,请参阅使用 @Bean 注释。

1.3.2. Instantiating Beans

bean 定义本质上是创建一个或多个对象的方法。 当被询问时,容器会查看命名 bean 的组成,并使用该 bean 定义封装的配置元数据来创建(或获取)实际对象。

如果使用基于 XML 的配置元数据,则指定要在 元素的 class 属性中实例化的对象的类型(或类)。 这个类属性(在内部,它是 BeanDefinition 实例上的 Class 属性)通常是强制性的。 (对于例外情况,请参阅使用实例工厂方法Bean 定义继承进行实例化。)您可以通过以下两种方式之一使用 Class 属性:(后续会将到)

通常,在容器本身通过反射调用其构造函数直接创建 bean 的情况下,指定要构造的 bean 类,有点等同于带有 new 运算符的 Java 代码。

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

嵌套类名
如果要为嵌套类配置 bean 定义,可以使用嵌套类的二进制名称或源名称。

例如,如果您在 com.example 包中有一个名为 SomeThing 的类,并且这个 SomeThing 类有一个名为 OtherThing 的静态嵌套类,则它们可以用美元符号 ($) 或点 (.) 分隔。 因此,bean 定义中类属性的值将是 com.example.SomeThing$OtherThing 或 com.example.SomeThing.OtherThing。

使用构造函数实例化