spring官網線上學習文件翻譯

先理後兵發表於2020-09-14

Core Technologies (核心技術)

  • Version 5.0.8.RELEASE

    • 版本5.0.8RELEASE
  • This part of the reference documentation covers all of those technologies that are absolutely integral to the Spring Framework.

    • 參考文件的這一部分涵蓋了對Spring框架絕對不可或缺的所有技術。
  • Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container. A thorough treatment of the Spring Framework’s IoC container is closely followed by comprehensive coverage of Spring’s Aspect-Oriented Programming (AOP) technologies. The Spring Framework has its own AOP framework, which is conceptually easy to understand, and which successfully addresses the 80% sweet spot of AOP requirements in Java enterprise programming.

    • 其中最重要的是Spring框架的控制反轉(IoC)容器。在全面介紹了Spring框架的IoC容器之後,緊接著是對Spring的面向切面程式設計(AOP)技術的全面介紹。Spring框架有自己的AOP框架,它在概念上很容易理解,並且成功地解決了Java企業程式設計中80%的AOP需求的最佳點。
  • Coverage of Spring’s integration with AspectJ (currently the richest - in terms of features - and certainly most mature AOP implementation in the Java enterprise space) is also provided.

    • 還介紹了Spring與AspectJ的整合(就特性而言,這是目前最豐富的,也是Java企業領域中最成熟的AOP實現)
    • AspectJ是一個面向切面的框架,它擴充套件了Java語言。AspectJ定義了AOP語法,它有一個專門的編譯器用來生成遵守Java位元組編碼規範的Class檔案。

1. The IoC container (IoC容器)

1.1 Introduction to the Spring IoC container and beans (Spring IoC容器和bean的介紹)

  • This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) [1] principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the Service Locator pattern.

    • 本章涵蓋了控制反轉(IoC)原理的Spring框架實現。IoC中包含依賴注入(DI)。這是一個過程,物件通過建構函式引數、工廠方法的引數或在物件例項被構造或從工廠方法返回後在物件例項上設定的屬性來定義它們的依賴項,也就是它們使用的其他物件。然後,容器在建立bean時注入這些依賴項。這個過程基本上是bean的逆過程,因此稱為控制反轉(IoC)
  • The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds easier integration with Spring’s AOP features; message resource handling (for use in internationalization), event publication; and application-layer specific contexts such as the WebApplicationContext for use in web applications.

    • org.springframework.beans和org.springframework.context包是Spring框架的IoC容器的基礎。BeanFactory(Bean工廠)介面提供了一種高階配置機制,能夠管理任何型別的物件。ApplicationContext是BeanFactory的子介面。它更容易與Spring的AOP特性整合;訊息資源處理(用於國際化)、事件釋出;和應用程式層特定的上下文,如web應用程式中使用的WebApplicationContext
  • In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory, and is used exclusively in this chapter in descriptions of Spring’s IoC container. For more information on using the BeanFactory instead of the ApplicationContext, refer to The BeanFactory.

    • 簡而言之,BeanFactory提供了配置框架和基本功能,而ApplicationContext新增了更多特定於企業的功能。ApplicationContext是BeanFactory的一個完整超集,在本章描述Spring的IoC容器時只使用它。有關使用BeanFactory而不是ApplicationContext的更多資訊,請參考>The BeanFactory
  • In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.

    • 在Spring中,構成應用程式主幹並且由Spring IoC容器管理的物件稱為beans.一個bean是由Spring IoC容器例項化、組裝和管理的物件。否則,bean只是應用程式中許多物件中的一個。bean及其之間的依賴關係反映在容器使用的配置後設資料中。

1.2 Container overview (容器概述)

  • The interface org.springframework.context.ApplicationContext represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the aforementioned beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It allows you to express the objects that compose your application and the rich interdependencies between such objects.

  • org.springframework.context的介面。ApplicationContext表示Spring IoC容器,並負責例項化、配置和組裝前面提到的bean。容器通過讀取配置後設資料獲得關於要例項化、配置和組裝哪些物件的指令。配置後設資料用XML、Java註釋或Java程式碼表示。它允許您表達組成應用程式的物件以及這些物件之間豐富的相互依賴關係。

  • Several implementations of the ApplicationContext interface are supplied out-of-the-box with Spring. In standalone applications it is common to create an instance of ClassPathXmlApplicationContext or FileSystemXmlApplicationContext. While XML has been the traditional format for defining configuration metadata you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats.

  • Spring提供了ApplicationContext介面的幾個現成實現。在獨立應用程式中,通常建立ClassPathXmlApplicationContext或FileSystemXmlApplicationContext的例項。雖然XML是定義配置後設資料的傳統格式,但您可以通過提供少量XML配置以宣告方式啟用對這些附加後設資料格式的支援,來指示容器使用Java註釋或程式碼作為後設資料格式。

  • In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. For example, in a web application scenario, a simple eight (or so) lines of boilerplate web descriptor XML in the web.xml file of the application will typically suffice (see Convenient ApplicationContext instantiation for web applications). If you are using the Spring Tool Suite Eclipse-powered development environment this boilerplate configuration can be easily created with few mouse clicks or keystrokes.

    The following diagram is a high-level view of how Spring works. Your application classes are combined with configuration metadata so that after the ApplicationContext is created and initialized, you have a fully configured and executable system or application.

    • 在大多數應用程式場景中,不需要顯式的使用者程式碼來例項化Spring IoC容器的一個或多個例項。例如,在web應用程式場景中,應用程式的web. XML檔案中簡單的8行(大約)樣板web描述符XML通常就足夠了(請參閱web應用程式的方便ApplicationContext例項化)。如果您使用的是Spring Tool Suite eclipse驅動的開發環境,那麼只需單擊幾下滑鼠或擊鍵,就可以輕鬆地建立這個樣板配置。

      下面的圖表是Spring如何執行的高階檢視

1.2.1. Configuration metadata (配置後設資料)
  • As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata; this configuration metadata represents how you as an application developer tell the Spring container to instantiate, configure, and assemble the objects in your application.

    • 正如前面的圖表所示,Spring IoC容器消耗一種配置後設資料;此配置後設資料表示您作為應用程式開發人員如何告訴Spring容器在應用程式中例項化、配置和組裝物件。
  • Configuration metadata is traditionally supplied in a simple and intuitive XML format, which is what most of this chapter uses to convey key concepts and features of the Spring IoC container.

    • 配置後設資料傳統上是以簡單直觀的XML格式提供的,本章的大部分內容都使用它來傳達Spring IoC容器的關鍵概念和特性。
  • XML-based metadata is not the only allowed form of configuration metadata. The Spring IoC container itself is totally decoupled from the format in which this configuration metadata is actually written. These days many developers choose Java-based configuration for their Spring applications.

    • 基於xml的後設資料並不是唯一允許的配置後設資料形式。Spring IoC容器本身與實際編寫配置後設資料的格式完全解耦。現在,許多開發人員為他們的Spring應用程式選擇基於java的配置。
  • For information about using other forms of metadata with the Spring container, see:

    • 有關在Spring容器中使用其他形式的後設資料的資訊,請參見:
  • Annotation-based configuration: Spring 2.5 introduced support for annotation-based configuration metadata.

    • 基於註釋的配置:Spring 2.5引入了對基於註釋的配置後設資料的支援。
  • Java-based configuration: Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. Thus you can define beans external to your application classes by using Java rather than XML files. To use these new features, see the @Configuration, @Bean, @Import and @DependsOn annotations.

  • Spring configuration consists of at least one and typically more than one bean definition that the container must manage. XML-based configuration metadata shows these beans configured as <bean/> elements inside a top-level <beans/> element. Java configuration typically uses @Bean annotated methods within a @Configuration class.

    • Spring配置由容器必須管理的至少一個(通常是多個)bean定義組成。基於xml的配置後設資料顯示這些bean被配置為頂級元素中的元素。Java配置通常在@Configuration類中使用@Bean註釋的方法。

    • 這些bean定義對應於組成應用程式的實際物件。通常需要定義服務層物件、資料訪問物件(dao)、表示物件(如Struts Action例項)、基礎設施物件(如Hibernate SessionFactories)、JMS佇列等等。通常不需要在容器中配置細粒度的域物件,因為建立和載入域物件通常是dao和業務邏輯的職責。但是,您可以使用Spring與AspectJ的整合來配置在IoC容器控制之外建立的物件。參見用Spring使用AspectJ來依賴注入域物件。

  • The following example shows the basic structure of XML-based configuration metadata:
    • 下面的示例展示了基於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="...">
        <!-- 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>
  • The id attribute is a string that you use to identify the individual bean definition. The class attribute defines the type of the bean and uses the fully qualified classname. The value of the id attribute refers to collaborating objects. The XML for referring to collaborating objects is not shown in this example; see Dependencies for more information.
    • id屬性是用於標識單個bean定義的字串。class屬性定義bean的型別,並使用完全限定的類名。id屬性的值引用協作物件。在這個例子中沒有顯示用於引用協作物件的XML;有關更多資訊,請參見依賴項。
1.2.2. Instantiating a container (例項化一個容器)
  • Instantiating a Spring IoC container is straightforward. The location path or paths supplied to an ApplicationContext constructor are actually resource strings that allow the container to load configuration metadata from a variety of external resources such as the local file system, from the Java CLASSPATH, and so on.
    • 例項化Spring IoC容器非常簡單。提供給ApplicationContext建構函式的位置路徑實際上是資源字串,允許容器從各種外部資源(如本地檔案系統、Java類路徑等)載入配置後設資料。
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
  • After you learn about Spring’s IoC container, you may want to know more about Spring’s Resource abstraction, as described in Resources, which provides a convenient mechanism for reading an InputStream from locations defined in a URI syntax. In particular, Resource paths are used to construct applications contexts as described in Application contexts and Resource paths.

    • 在瞭解了Spring的IoC容器之後,您可能想了解更多關於Spring的資源抽象的資訊,如參考資料中所述,它提供了一種方便的機制,可以從URI語法中定義的位置讀取InputStream。特別地,資源路徑用於構建應用程式上下文(如應用程式上下文和資源路徑中所述)。
  • The following example shows the service layer objects (services.xml) configuration file:

    • 下面的例子顯示了服務層物件(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"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

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

</beans>
  • The following example shows the data access objects daos.xml file:
    • 下面的例子顯示了資料訪問物件dao .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">
        <!-- 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>
  • In the preceding example, the service layer consists of the class PetStoreServiceImpl, and two data access objects of the type JpaAccountDao and JpaItemDao (based on the JPA Object/Relational mapping standard). The property name element refers to the name of the JavaBean property, and the ref element refers to the name of another bean definition. This linkage between id and ref elements expresses the dependency between collaborating objects. For details of configuring an object’s dependencies, see Dependencies.
    • 在前面的示例中,服務層由類PetStoreServiceImpl和型別為JpaAccountDao和JpaItemDao的兩個資料訪問物件(基於JPA物件/關係對映標準)組成。property name元素引用JavaBean屬性的名稱,ref元素引用另一個bean定義的名稱。id和ref元素之間的連結表示了協作物件之間的依賴關係。有關配置物件依賴項的詳細資訊,請參見依賴項。
Composing XML-based configuration metadata (組合基於xml的配置後設資料)
  • It can be useful to have bean definitions span multiple XML files. Often each individual XML configuration file represents a logical layer or module in your architecture.

    • 讓bean定義跨越多個XML檔案可能很有用。通常,每個單獨的XML配置檔案表示體系結構中的一個邏輯層或模組。
  • You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource locations, as was shown in the previous section. Alternatively, use one or more occurrences of the <import/> element to load bean definitions from another file or files. For example:

    • 您可以使用應用程式上下文建構函式從所有這些XML片段載入bean定義。此建構函式接受多個資源位置,如前一節所示。或者,使用元素的一次或多次出現來從另一個或多個檔案載入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>
  • In the preceding example, external bean definitions are loaded from three files: services.xml, messageSource.xml, and themeSource.xml. All location paths are relative to the definition file doing the importing, so services.xml must be in the same directory or classpath location as the file doing the importing, while messageSource.xml and themeSource.xml must be in a resources location below the location of the importing file. As you can see, a leading slash is ignored, but given that these paths are relative, it is better form not to use the slash at all. The contents of the files being imported, including the top level <beans/> element, must be valid XML bean definitions according to the Spring Schema.

    • 在前面的示例中,外部bean定義是從三個檔案載入的:服務。xml, messageSource。xml和themeSource.xml。所有位置路徑都相對於執行匯入的定義檔案,因此services.xml必須與執行匯入的檔案位於相同的目錄或類路徑位置,而messageSource.xml和themeSource.xml必須位於匯入檔案位置下方的資源位置。正如您所看到的,前面的斜槓被忽略了,但是考慮到這些路徑是相對的,最好完全不使用斜槓。正在匯入的檔案內容
  • It is possible, but not recommended, to reference files in parent directories using a relative "../" path. Doing so creates a dependency on a file that is outside the current application. In particular, this reference is not recommended for "classpath:" URLs (for example, "classpath:../services.xml"), where the runtime resolution process chooses the "nearest" classpath root and then looks into its parent directory. Classpath configuration changes may lead to the choice of a different, incorrect directory.

    • 這是可能的,但不建議,在父目錄引用檔案使用一個親戚"../”路徑。這樣做會在當前應用程式之外的檔案上建立一個依賴項。特別是,不建議對“classpath:”url(例如,“classpath:../services.xml”)引用此引用,其中執行時解析過程選擇“最近的”類路徑根,然後檢視其父目錄。類路徑配置更改可能導致選擇不同的、不正確的目錄。
  • You can always use fully qualified resource locations instead of relative paths: for example, "file:C:/config/services.xml" or "classpath:/config/services.xml". However, be aware that you are coupling your application’s configuration to specific absolute locations. It is generally preferable to keep an indirection for such absolute locations, for example, through "${…}" placeholders that are resolved against JVM system properties at runtime.

    • 您可以始終使用完全限定的資源位置,而不是相對路徑:例如,“file:C:/config/services”。xml”或“類路徑:/配置/ services . xml”。但是,請注意,您正在將應用程式的配置耦合到特定的絕對位置。通常最好為這樣的絕對位置保留一個間接性,例如,通過在執行時根據JVM系統屬性解析的“${…}”佔位符。
  • The import directive is a feature provided by the beans namespace itself. Further configuration features beyond plain bean definitions are available in a selection of XML namespaces provided by Spring, e.g. the "context" and the "util" namespace.

    • 匯入指令是bean名稱空間本身提供的特性。除了普通bean定義之外,Spring提供的XML名稱空間還提供了更多的配置特性,例如“context”和“util”名稱空間。
The Groovy Bean Definition DSL (Groovy Bean定義DSL)
  • As a further example for externalized configuration metadata, bean definitions can also be expressed in Spring’s Groovy Bean Definition DSL, as known from the Grails framework. Typically, such configuration will live in a ".groovy" file with a structure as follows:
    • 作為外部化配置後設資料的進一步示例,bean定義也可以在Spring的Groovy bean定義DSL中表示,正如Grails框架中所知道的那樣。通常,這樣的配置將存在於“。檔案的結構如下:
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
        }
    }
}
  • This configuration style is largely equivalent to XML bean definitions and even supports Spring’s XML configuration namespaces. It also allows for importing XML bean definition files through an "importBeans" directive.
    • 這種配置風格在很大程度上等同於XML bean定義,甚至支援Spring的XML配置名稱空間。它還允許通過“importBeans”指令匯入XML bean定義檔案。
1.2.3. Using the container (使用容器[spring])
  • The ApplicationContext is the interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. Using the method T getBean(String name, Class<T> requiredType) you can retrieve instances of your bean

    • ApplicationContext是一個高階工廠的介面,該工廠能夠維護不同bean及其依賴項的登錄檔。使用方法T getBean(字串名,類 requiredType),您可以檢索bean的例項
  • The ApplicationContext enables you to read bean definitions and access them as follows:

    • 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();
  • With Groovy configuration, bootstrapping looks very similar, just a different context implementation class which is Groovy-aware (but also understands XML bean definitions):
    • 使用Groovy配置,bootstrapping看起來非常相似,只是一個不同的上下文實現類,它支援Groovy(但也理解XML bean定義):
ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");
  • The most flexible variant is GenericApplicationContext in combination with reader delegates, e.g. with XmlBeanDefinitionReader for XML files:
    • 最靈活的變體是GenericApplicationContext與reader委託的結合,例如XmlBeanDefinitionReader用於XML檔案:
GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();
  • Or with GroovyBeanDefinitionReader for Groovy files:
    • 或者對Groovy檔案使用GroovyBeanDefinitionReader:
GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
context.refresh();
  • Such reader delegates can be mixed and matched on the same ApplicationContext, reading bean definitions from diverse configuration sources, if desired.

    • 這樣的閱讀器委託可以在相同的ApplicationContext上混合和匹配,如果需要,可以從不同的配置源讀取bean定義
  • You can then use getBean to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but ideally your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all, and thus no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, allowing you to declare a dependency on a specific bean through metadata (e.g. an autowiring annotation).

    • 然後可以使用getBean檢索bean的例項。ApplicationContext介面有一些其他檢索bean的方法,但理想情況下,應用程式程式碼不應該使用它們。實際上,您的應用程式程式碼根本不應該呼叫getBean()方法,因此根本不依賴於Spring api。例如,Spring與web框架的整合為各種web框架元件(如控制器和jsf管理的bean)提供依賴注入,允許您通過後設資料(例如自動裝配註釋)宣告對特定bean的依賴。

1.3. Bean overview (Bean概述)

  • A Spring IoC container manages one or more beans. These beans are created with the configuration metadata that you supply to the container, for example, in the form of XML <bean/> definitions.

    • Spring IoC容器管理一個或多個bean。這些bean是使用您提供給容器的配置後設資料建立的,例如,以XML 定義的形式
  • Within the container itself, these bean definitions are represented as BeanDefinition objects, which contain (among other information) the following metadata:

    • 在容器本身內,這些bean定義被表示為BeanDefinition物件,其中包含(以及其他資訊)以下後設資料:
      • A package-qualified class name: typically the actual implementation class of the bean being defined.
        • 一個包限定的類名:通常是被定義的bean的實際實現類。
      • Bean behavioral configuration elements, which state how the bean should behave in the container (scope, lifecycle callbacks, and so forth).
        • Bean行為配置元素,它宣告Bean在容器中應該如何行為(範圍、生命週期回撥,等等)
      • References to other beans that are needed for the bean to do its work; these references are also called collaborators or dependencies.
        • 對bean執行其工作所需的其他bean的引用;這些引用也稱為協作者或依賴項。
      • Other configuration settings to set in the newly created object, for example, the number of connections to use in a bean that manages a connection pool, or the size limit of the pool.
        • 在新建立的物件中要設定的其他配置設定,例如,在管理連線池的bean中要使用的連線數,或者池的大小限制。
  • This metadata translates to a set of properties that make up each bean definition.

    • 該後設資料轉換為組成每個bean定義的一組屬性。
  • Table 1. The bean definition

    • bean定義
Property(屬性) Explained in…(解釋...)
class(類) Instantiating beans (例項化bean)
name(名字) Naming beans (命名bean)
scope(範圍) Bean scopes (bean範圍)
constructor arguments(建構函式引數) Dependency Injection (依賴注入)
properties(屬性) Dependency Injection
autowiring mode(自動裝配模式) Autowiring collaborators (自動裝配的合作者)
lazy-initialization mode(延遲初始化模式) Lazy-initialized beans (延遲初始化的bean)
initialization method(初始化方法) Initialization callbacks (初始化方法的回撥)
destruction method(破壞的方法) Destruction callbacks (破壞方法的回撥)
  • In addition to bean definitions that contain information on how to create a specific bean, the ApplicationContext implementations also permit the registration of existing objects that are created outside the container, by users. This is done by accessing the ApplicationContext’s BeanFactory via the method getBeanFactory() which returns the BeanFactory implementation DefaultListableBeanFactory. DefaultListableBeanFactory supports this registration through the methods registerSingleton(..) and registerBeanDefinition(..). However, typical applications work solely with beans defined through metadata bean definitions.

    • 除了包含關於如何建立特定bean的資訊的bean定義之外,ApplicationContext實現還允許註冊由使用者在容器外部建立的現有物件。這是通過getBeanFactory()方法訪問ApplicationContext的BeanFactory來完成的,該方法返回BeanFactory實現DefaultListableBeanFactory。DefaultListableBeanFactory通過registerSingleton(..)和registerBeanDefinition(..)方法支援這種註冊。但是,典型的應用程式只使用通過metada定義的bean
  • Bean metadata and manually supplied singleton instances need to be registered as early as possible, in order for the container to properly reason about them during autowiring and other introspection steps. While overriding of existing metadata and existing singleton instances is supported to some degree, the registration of new beans at runtime (concurrently with live access to factory) is not officially supported and may lead to concurrent access exceptions and/or inconsistent state in the bean container.

    • Bean後設資料和手動提供的單例例項需要儘可能早地註冊,以便容器在自動裝配和其他自省步驟中正確地對它們進行推理。雖然在某種程度上支援覆蓋現有後設資料和現有的單例例項,但在執行時註冊新bean(與對工廠的實時訪問併發)不受官方支援,並且可能導致bean容器中的併發訪問異常和/或不一致狀態。
1.3.1. Naming beans (命名bean)
  • Every bean has one or more identifiers. These identifiers must be unique within the container that hosts the bean. A bean usually has only one identifier, but if it requires more than one, the extra ones can be considered aliases.

    • 每個bean都有一個或多個識別符號。這些識別符號在宿主bean的容器中必須是唯一的。一個bean通常只有一個識別符號,但是如果它需要多個識別符號,那麼多餘的識別符號可以被視為別名。
  • In XML-based configuration metadata, you use the id and/or name attributes to specify the bean identifier(s). The id attribute allows you to specify exactly one id. Conventionally these names are alphanumeric ('myBean', 'fooService', etc.), but may contain special characters as well. If you want to introduce other aliases to the bean, you can also specify them in the name attribute, separated by a comma (,), semicolon (;), or white space. As a historical note, in versions prior to Spring 3.1, the id attribute was defined as an xsd:ID type, which constrained possible characters. As of 3.1, it is defined as an xsd:string type. Note that bean id uniqueness is still enforced by the container, though no longer by XML parsers.

    • 在基於xml的配置後設資料中,您使用id和/或name屬性來指定bean識別符號。id屬性允許您精確地指定一個id。通常這些名稱是字母數字('myBean', 'fooService'等),但也可能包含特殊字元。如果希望為bean引入其他別名,還可以在name屬性中指定它們,用逗號(,)、分號(;)或空格分隔。作為一個歷史記錄,在Spring 3.1之前的版本中,id屬性被定義為xsd: id型別,它限制了可能的字元。在3.1版本中,it i
  • You are not required to supply a name or id for a bean. If no name or id is supplied explicitly, the container generates a unique name for that bean. However, if you want to refer to that bean by name, through the use of the ref element or Service Locator style lookup, you must provide a name. Motivations for not supplying a name are related to using inner beans and autowiring collaborators.

    • 您不需要為bean提供名稱或id。如果沒有顯式地提供名稱或id,容器將為該bean生成惟一的名稱。但是,如果您希望通過使用ref元素或服務定位器樣式查詢通過名稱引用那個bean,那麼您必須提供一個名稱。不提供名稱的動機與使用內部bean和自動裝配協作者有關。
  • Bean Naming Conventions

    • bean命名約定
  • The convention is to use the standard Java convention for instance field names when naming beans. That is, bean names start with a lowercase letter, and are camel-cased from then on. Examples of such names would be (without quotes) 'accountManager', 'accountService', 'userDao', 'loginController', and so forth.

    • 約定是在命名bean時對例項欄位名使用標準Java約定。也就是說,bean名稱以小寫字母開頭,此後採用駝峰大小寫。這些名稱的例子如下(不加引號)“accountManager”、“accountService”、“userDao”、“loginController”等等。
  • Naming beans consistently makes your configuration easier to read and understand, and if you are using Spring AOP it helps a lot when applying advice to a set of beans related by name.

    • 一致地命名bean可以使您的配置更容易閱讀和理解,如果您正在使用Spring AOP,那麼在將通知應用到一組名稱相關的bean時,它會有很大幫助。
  • With component scanning in the classpath, Spring generates bean names for unnamed components, following the rules above: essentially, taking the simple class name and turning its initial character to lower-case. However, in the (unusual) special case when there is more than one character and both the first and second characters are upper case, the original casing gets preserved. These are the same rules as defined by java.beans.Introspector.decapitalize (which Spring is using here).

    • 通過在類路徑中掃描元件,Spring為未命名的元件生成bean名稱,遵循上面的規則:本質上,採用簡單的類名並將其初始字元轉換為小寫。但是,在有多個字元並且第一個和第二個字元都是大寫的(不尋常的)特殊情況下,原始的外殼將被保留。這些規則與java.bean .內省器.decapitalize(此處Spring使用的)定義的規則相同
Aliasing a bean outside the bean definition (在bean定義之外混疊一個bean)
  • In a bean definition itself, you can supply more than one name for the bean, by using a combination of up to one name specified by the id attribute, and any number of other names in the name attribute. These names can be equivalent aliases to the same bean, and are useful for some situations, such as allowing each component in an application to refer to a common dependency by using a bean name that is specific to that component itself.

    • 在bean定義本身中,您可以為bean提供多個名稱,方法是使用由id屬性指定的最多一個名稱和name屬性中任意數量的其他名稱的組合。這些名稱可以是相同bean的等價別名,並且在某些情況下非常有用,例如允許應用程式中的每個元件通過使用特定於該元件本身的bean名稱來引用公共依賴項。
  • Specifying all aliases where the bean is actually defined is not always adequate, however. It is sometimes desirable to introduce an alias for a bean that is defined elsewhere. This is commonly the case in large systems where configuration is split amongst each subsystem, each subsystem having its own set of object definitions. In XML-based configuration metadata, you can use the <alias/> element to accomplish this.

    • 然而,指定實際定義bean的所有別名並不總是足夠的。有時需要為在別處定義的bean引入別名。在大型系統中,配置在每個子系統之間分割,每個子系統都有自己的一組物件定義,這種情況很常見。在基於xml的配置後設資料中,可以使用元素來完成此任務。
<alias name="fromName" alias="toName"/>
  • In this case, a bean in the same container which is named fromName, may also, after the use of this alias definition, be referred to as toName.

    • 在這種情況下,在使用別名定義之後,同一個容器中名為fromName的bean也可以被稱為toName。
  • For example, the configuration metadata for subsystem A may refer to a DataSource via the name subsystemA-dataSource. The configuration metadata for subsystem B may refer to a DataSource via the name subsystemB-dataSource. When composing the main application that uses both these subsystems the main application refers to the DataSource via the name myApp-dataSource. To have all three names refer to the same object you add to the MyApp configuration metadata the following aliases definitions:

    • 例如,子系統A的配置後設資料可以通過名稱subsystem - DataSource引用資料來源。子系統B的配置後設資料可以通過名稱subsystembl - DataSource引用資料來源。在編寫同時使用這兩個子系統的主應用程式時,主應用程式通過名稱myApp-dataSource引用資料來源。為了讓這三個名字都指向你新增到MyApp配置後設資料中的同一個物件,下面的別名定義如下:
<alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/>
<alias name="subsystemA-dataSource" alias="myApp-dataSource" />
  • Now each component and the main application can refer to the dataSource through a name that is unique and guaranteed not to clash with any other definition (effectively creating a namespace), yet they refer to the same bean.

    • 現在,每個元件和主應用程式都可以通過一個惟一的並且保證不會與任何其他定義衝突的名稱(有效地建立了一個名稱空間)引用資料來源,但是它們引用的是同一個bean。
  • Java-configuration

    • java配置
  • If you are using Java-configuration, the @Bean annotation can be used to provide aliases see Using the @Bean annotation for details.

    • 如果您正在使用Java-configuration,則可以使用@Bean註釋來提供別名,詳見使用@Bean註釋獲得的詳細資訊。
1.3.2. Instantiating beans (例項化bean)
  • A bean definition essentially is a recipe for creating one or more objects. The container looks at the recipe for a named bean when asked, and uses the configuration metadata encapsulated by that bean definition to create (or acquire) an actual object.

    • bean定義本質上是建立一個或多個物件的配方。當請求時,容器檢視已命名bean的配方,並使用該bean定義封裝的配置後設資料來建立(或獲取)實際物件。
  • If you use XML-based configuration metadata, you specify the type (or class) of object that is to be instantiated in the class attribute of the <bean/> element. This class attribute, which internally is a Class property on a BeanDefinition instance, is usually mandatory. (For exceptions, see Instantiation using an instance factory method and Bean definition inheritance.) You use the Class property in one of two ways:

    • 如果使用基於xml的配置後設資料,則指定要在元素的class屬性中例項化的物件的型別(或類)。這個類屬性在內部是BeanDefinition例項上的類屬性,通常是必需的。(有關異常,請參閱使用例項工廠方法和Bean定義繼承進行例項化。)使用Class屬性有兩種方式:
      • Typically, to specify the bean class to be constructed in the case where the container itself directly creates the bean by calling its constructor reflectively, somewhat equivalent to Java code using the new operator.
        • 通常,在容器本身通過反射呼叫其建構函式直接建立bean的情況下,指定要構造的bean類,這在某種程度上等同於使用new操作符的Java程式碼。
      • To specify the actual class containing the static factory method that will be invoked to create the object, in the less common case where the container invokes a static factory method on a class to create the bean. The object type returned from the invocation of the static factory method may be the same class or another class entirely.
        • 為了指定包含將被呼叫來建立物件的靜態工廠方法的實際類,在容器呼叫類上的靜態工廠方法來建立bean的不太常見的情況下。從靜態工廠方法呼叫返回的物件型別可以是相同的類,也可以完全是另一個類。

Inner class names

    • 內部類的名字

    If you want to configure a bean definition for a static nested class, you have to use the binary name of the nested class.

    • 如果希望為靜態巢狀類配置bean定義,則必須使用巢狀類的二進位制名稱。

      For example, if you have a class called Foo in the com.example package, and this Foo class has a static nested class called Bar, the value of the 'class' attribute on a bean definition would be…

      com.example.Foo$Bar

      • 例如,如果你在com中有一個叫做Foo的類。這個Foo類有一個靜態巢狀的類,叫做Bar, bean定義上的class屬性的值將是…

        com.example.Foo$Bar
        

        Notice the use of the $ character in the name to separate the nested class name from the outer class name.

        • 請注意名稱中使用了$字元來分隔巢狀的類名和外部類名。
Instantiation with a constructor (用建構函式例項化)
  • When you create a bean by the constructor approach, all normal classes are usable by and compatible with Spring. That is, the class being developed does not need to implement any specific interfaces or to be coded in a specific fashion. Simply specifying the bean class should suffice. However, depending on what type of IoC you use for that specific bean, you may need a default (empty) constructor.

    • 當您通過建構函式方法建立bean時,所有的普通類都可以通過Spring使用並與之相容。也就是說,被開發的類不需要實現任何特定的介面,也不需要以特定的方式進行編碼。簡單地指定bean類就足夠了。但是,根據您為特定bean使用的IoC型別,您可能需要一個預設的(空的)建構函式。
  • The Spring IoC container can manage virtually any class you want it to manage; it is not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans with only a default (no-argument) constructor and appropriate setters and getters modeled after the properties in the container. You can also have more exotic non-bean-style classes in your container. If, for example, you need to use a legacy connection pool that absolutely does not adhere to the JavaBean specification, Spring can manage it as well.

    • Spring IoC容器實際上可以管理任何您希望它管理的類;它並不侷限於管理真正的javabean。大多數Spring使用者更喜歡實際的javabean,它只有一個預設的(無引數的)建構函式和適當的setter和getter方法,這些方法是根據容器中的屬性建模的。您還可以在容器中使用更多奇異的非bean樣式的類。例如,如果您需要使用絕對不符合JavaBean規範的遺留連線池,Spring也可以管理它。
  • With XML-based configuration metadata you can specify your bean class as follows:

    • 使用基於xml的配置後設資料,您可以指定您的bean類如下:
<bean id="exampleBean" class="examples.ExampleBean"/>

<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
  • For details about the mechanism for supplying arguments to the constructor (if required) and setting object instance properties after the object is constructed, see Injecting Dependencies.
    • 有關向建構函式提供引數(如果需要)和在構造物件後設定物件例項屬性的機制的詳細資訊,請參見注入依賴項。
Instantiation with a static factory method (用靜態工廠方法例項化)
  • When defining a bean that you create with a static factory method, you use the class attribute to specify the class containing the static factory method and an attribute named factory-method to specify the name of the factory method itself. You should be able to call this method (with optional arguments as described later) and return a live object, which subsequently is treated as if it had been created through a constructor. One use for such a bean definition is to call static factories in legacy code.

    • 在定義使用靜態工廠方法建立的bean時,您使用class屬性來指定包含靜態工廠方法的類,使用名為factory-method的屬性來指定工廠方法本身的名稱。您應該能夠呼叫這個方法(後面將介紹可選引數)並返回一個活動物件,然後將其視為通過建構函式建立的。這種bean定義的一個用途是在遺留程式碼中呼叫靜態工廠。
  • The following bean definition specifies that the bean will be created by calling a factory-method. The definition does not specify the type (class) of the returned object, only the class containing the factory method. In this example, the createInstance() method must be a static method.

    • 下面的bean定義指定該bean將通過呼叫工廠方法來建立。該定義沒有指定返回物件的型別(類),只指定包含工廠方法的類。在本例中,createInstance()方法必須是靜態方法。
<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;
    }
}
  • For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after the object is returned from the factory, see Dependencies and configuration in detail.
    • 有關向工廠方法提供(可選)引數和在物件從工廠返回後設定物件例項屬性的機制的詳細資訊,請參見依賴項和配置。
Instantiation using an instance factory method (使用例項工廠方法例項化)
  • Similar to instantiation through a static factory method, instantiation with an instance factory method invokes a non-static method of an existing bean from the container to create a new bean. To use this mechanism, leave the class attribute empty, and in the factory-bean attribute, specify the name of a bean in the current (or parent/ancestor) container that contains the instance method that is to be invoked to create the object. Set the name of the factory method itself with the factory-method attribute.
    • 與通過靜態工廠方法進行例項化類似,例項工廠方法的例項化從容器中呼叫現有bean的非靜態方法來建立新bean。要使用這種機制,請將class屬性保留為空,並在factory-bean屬性中指定當前(或父/祖先)容器中bean的名稱,該容器包含要呼叫來建立物件的例項方法。使用factory-method屬性設定工廠方法本身的名稱。
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<!-- the bean to be created via the factory bean -->
<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>
public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();

    public ClientService createClientServiceInstance() {
        return clientService;
    }
}
  • One factory class can also hold more than one factory method as shown here:
    • 一個工廠類也可以包含多個工廠方法,如下所示:
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</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();

    public ClientService createClientServiceInstance() {
        return clientService;
    }

    public AccountService createAccountServiceInstance() {
        return accountService;
    }
}
  • This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See Dependencies and configuration in detail.

    • 這種方法表明可以通過依賴項注入(DI)來管理和配置工廠bean本身。請詳細檢視依賴關係和配置。
  • In Spring documentation, factory bean refers to a bean that is configured in the Spring container that will create objects through an instance or static factory method. By contrast, FactoryBean (notice the capitalization) refers to a Spring-specific FactoryBean .

    • 在Spring文件中,工廠bean指的是在Spring容器中配置的bean,該bean將通過例項或靜態工廠方法建立物件。相比之下,FactoryBean(注意大小寫)指的是特定於spring的FactoryBean。

1.4. Dependencies (依賴)

  • A typical enterprise application does not consist of a single object (or bean in the Spring parlance). Even the simplest application has a few objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal.
    • 典型的企業應用程式不包含單個物件(或者用Spring的說法就是bean)。即使是最簡單的應用程式也有一些共同工作的物件來呈現終端使用者所看到的一致的應用程式。下一節將解釋如何從定義大量獨立的bean定義到一個完全實現的應用程式,其中物件可以協作來實現目標。
1.4.1. Dependency Injection (依賴注入)
  • Dependency injection (DI) is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes, or the Service Locator pattern.

    • 依賴注入(Dependency injection, DI)是一個過程,物件通過建構函式引數、工廠方法的引數或在構造或從工廠方法返回後在物件例項上設定的屬性來定義它們的依賴,也就是它們使用的其他物件。然後,容器在建立bean時注入這些依賴項。這個過程基本上是bean本身的逆過程,因此稱為控制反轉(IoC),它通過使用類的直接構造(S)來控制其依賴項的例項化或位置
  • Code is cleaner with the DI principle and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies, and does not know the location or class of the dependencies. As such, your classes become easier to test, in particular when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests.

    • 使用DI原則,程式碼會更清晰,並且當物件帶有依賴項時,解耦會更有效。物件不查詢其依賴項,也不知道依賴項的位置或類。因此,您的類變得更容易測試,特別是當依賴關係是在介面或抽象基類上時,它們允許在單元測試中使用存根或模擬實現。
  • DI exists in two major variants, Constructor-based dependency injection and Setter-based dependency injection.

    • 依賴注入有兩種主要的變體,即基於構造器的依賴注入和基於setter的依賴注入。
Constructor-based dependency injection (Constructor-based依賴注入)
  • Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency. Calling a static factory method with specific arguments to construct the bean is nearly equivalent, and this discussion treats arguments to a constructor and to a static factory method similarly. The following example shows a class that can only be dependency-injected with constructor injection. Notice that there is nothing special about this class, it is a POJO that has no dependencies on container specific interfaces, base classes or annotations.
    • 基於構造器的DI是由容器呼叫帶有許多引數的構造器來完成的,每個參數列示一個依賴項。呼叫帶有特定引數的靜態工廠方法來構造bean幾乎是等效的,本討論對建構函式的引數和靜態工廠方法的處理是類似的。下面的示例顯示了只能通過建構函式注入進行依賴注入的類。請注意,這個類沒有什麼特別之處,它是一個POJO,不依賴於容器特定的介面、基類或註釋。
public class SimpleMovieLister {

    // the SimpleMovieLister has a dependency on a MovieFinder
    private MovieFinder movieFinder;

    // a constructor so that the Spring container can inject a MovieFinder
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // business logic that actually uses the injected MovieFinder is omitted...
}
  • Constructor argument resolution

    • 建構函式引數解析
  • Constructor argument resolution matching occurs using the argument’s type. If no potential ambiguity exists in the constructor arguments of a bean definition, then the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated. Consider the following class:

    • 建構函式引數解析匹配使用引數的型別。如果bean定義的建構函式引數中不存在潛在的歧義,那麼建構函式引數在bean定義中定義的順序就是例項化bean時將這些引數提供給適當的建構函式的順序。考慮以下類:
package x.y;

public class Foo {

    public Foo(Bar bar, Baz baz) {
        // ...
    }
}
  • No potential ambiguity exists, assuming that Bar and Baz classes are not related by inheritance. Thus the following configuration works fine, and you do not need to specify the constructor argument indexes and/or types explicitly in the <constructor-arg/> element.
    • 假設Bar和Baz類不通過繼承關聯,則不存在潛在的歧義。因此,以下配置可以很好地工作,您不需要在元素中顯式地指定建構函式引數索引和/或型別。
<beans>
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/>
        <constructor-arg ref="baz"/>
    </bean>

    <bean id="bar" class="x.y.Bar"/>

    <bean id="baz" class="x.y.Baz"/>
</beans>
  • When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as <value>true</value>, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class:
    • 當引用另一個bean時,型別是已知的,可以進行匹配(就像前面的例子一樣)。當使用簡單型別時,例如true, Spring無法確定值的型別,因此如果沒有幫助,就無法按型別進行匹配。考慮以下類
package examples;

public class ExampleBean {

    // Number of years to calculate the Ultimate Answer
    private int years;

    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;

    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
  • Constructor argument type matching

    • 建構函式引數型別匹配
  • In the preceding scenario, the container can use type matching with simple types if you explicitly specify the type of the constructor argument using the type attribute. For example:

    • 在前面的場景中,如果使用type屬性顯式地指定建構函式引數的型別,則容器可以使用簡單型別的型別匹配。例
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>
  • Constructor argument index

    • 建構函式引數指標
  • Use the index attribute to specify explicitly the index of constructor arguments. For example:

    • 使用index屬性顯式地指定建構函式引數的索引。例如:
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>
  • In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type. Note that the index is 0 based

    • 除了解決多個簡單值的模糊性之外,指定索引還可以解決建構函式有兩個相同型別的引數時的模糊性。注意,索引是基於0的。
  • Constructor argument name

    • 建構函式引數的名字
  • You can also use the constructor parameter name for value disambiguation:

    • 也可以使用建構函式引數名來消除值的歧義:
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>
  • Keep in mind that to make this work out of the box your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you can’t compile your code with debug flag (or don’t want to) you can use @ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows:
    • 請記住,要做到開箱即用,您的程式碼必須在啟用除錯標誌的情況下進行編譯,以便Spring可以從建構函式中查詢引數名。如果不能使用除錯標誌(或不想這樣做)編譯程式碼,可以使用@ConstructorProperties JDK註釋顯式地命名建構函式引數。然後,樣例類必須看起來像這樣:
package examples;

public class ExampleBean {

    // Fields omitted

    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
Setter-based dependency injection (Setter-based依賴注入)
  • Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or no-argument static factory method to instantiate your bean.

    • 基於setter的DI是由容器在呼叫無引數建構函式或無引數靜態工廠方法來例項化bean之後呼叫bean上的setter方法來完成的。
  • The following example shows a class that can only be dependency-injected using pure setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes or annotations.

    • 下面的示例展示了一個只能使用純setter注入進行依賴注入的類。這個類是傳統的Java。它是一個POJO,不依賴於容器特定的介面、基類或註釋。
public class SimpleMovieLister {

    // the SimpleMovieLister has a dependency on the MovieFinder
    private MovieFinder movieFinder;

    // a setter method so that the Spring container can inject a MovieFinder
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // business logic that actually uses the injected MovieFinder is omitted...
}
  • The ApplicationContext supports constructor-based and setter-based DI for the beans it manages. It also supports setter-based DI after some dependencies have already been injected through the constructor approach. You configure the dependencies in the form of a BeanDefinition, which you use in conjunction with PropertyEditor instances to convert properties from one format to another. However, most Spring users do not work with these classes directly (i.e., programmatically) but rather with XML bean definitions, annotated components (i.e., classes annotated with @Component, @Controller, etc.), or @Bean methods in Java-based @Configuration classes. These sources are then converted internally into instances of BeanDefinition and used to load an entire Spring IoC container instance.
    • ApplicationContext為它管理的bean支援基於構造器和基於setter的DI。在已經通過建構函式方法注入了一些依賴項之後,它還支援基於setter的DI。您以BeanDefinition的形式配置依賴項,您將它與PropertyEditor例項一起使用,以將屬性從一種格式轉換為另一種格式。然而,大多數Spring使用者並不直接使用這些類(即,通過程式設計),而是使用XML bean定義、帶註釋的元件(即,帶@Component、@Controller等註釋的類),

Constructor-based or setter-based DI?

Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Required annotation on a setter method can be used to make the property a required dependency.

    • 由於可以混合使用基於構造器和基於setter的DI,對於強制依賴項使用構造器,而對於可選依賴項使用setter方法或配置方法,這是一個很好的經驗法則。注意,在setter方法上使用@Required註釋可以使屬性成為必需的依賴項

The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

    • Spring團隊通常提倡建構函式注入,因為它允許將應用程式元件實現為不可變物件,並確保所需的依賴關係不為空。此外,構造注入的元件總是以完全初始化的狀態返回給客戶端(呼叫)程式碼。順便提一下,大量的建構函式引數是一種糟糕的程式碼味道,這意味著類可能有太多的責任,應該進行重構以更好地解決問題的適當分離

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

    • Setter注入應該主要用於可選的依賴項,這些依賴項可以在類中分配合理的預設值。否則,必須在程式碼使用依賴項的任何地方執行非空檢查。setter注入的一個好處是,setter方法使該類的物件易於稍後重新配置或重新注入。因此,通過JMX mbean進行管理是setter注入的一個引人注目的用例。

Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

    • 使用對特定類最有意義的DI樣式。有時,在處理沒有原始碼的第三方類時,需要自己做出選擇。例如,如果第三方類不公開任何setter方法,那麼建構函式注入可能是DI的唯一可用形式。
Dependency resolution process (依賴性解析過程)
  • The container performs bean dependency resolution as follows:

    • 容器執行如下的bean依賴項解析:
      • The ApplicationContext is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified via XML, Java code, or annotations
        • 用描述所有bean的配置後設資料建立和初始化ApplicationContext。配置後設資料可以通過XML、Java程式碼或註釋指定。.
      • For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static-factory method if you are using that instead of a normal constructor. These dependencies are provided to the bean, when the bean is actually created.
        • 對於每個bean,其依賴關係以屬性、建構函式引數或靜態工廠方法引數(如果使用靜態工廠方法而不是普通建構函式)的形式表示。當bean被實際建立時,這些依賴項被提供給bean。
      • Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container.
        • 每個屬性或建構函式引數都是要設定的值的實際定義,或者是對容器中另一個bean的引用。
      • Each property or constructor argument which is a value is converted from its specified format to the actual type of that property or constructor argument. By default Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, etc.
        • 作為值的每個屬性或建構函式引數都從其指定的格式轉換為該屬性或建構函式引數的實際型別。預設情況下,Spring可以將字串格式提供的值轉換為所有內建型別,如int、long、string、boolean等。
  • The Spring container validates the configuration of each bean as the container is created. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Bean scopes. Otherwise, the bean is created only when it is requested. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies' dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late, i.e. on first creation of the affected bean.

    • 在建立容器時,Spring容器驗證每個bean的配置。但是,bean屬性本身在實際建立bean之前是不會設定的。在建立容器時,將建立單例範圍並設定為預例項化(預設值)的bean。作用域在Bean作用域中定義。否則,只在請求bean時建立它。建立一個bean可能會導致建立一個bean圖,因為建立和分配了bean的依賴項和它的依賴項的依賴項(等等)。注意,解決方案之間不匹配

Circular dependencies

    • 迴圈依賴

If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario.

    • 如果您主要使用建構函式注入,那麼可以建立一個無法解決的迴圈依賴場景

For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException.

    • 例如:類A通過建構函式注入需要一個類B的例項,類B通過建構函式注入需要一個類A的例項。如果您為類A和類B配置了相互注入的bean,那麼Spring IoC容器在執行時檢測到這個迴圈引用,並丟擲BeanCurrentlyInCreationException

One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.

    • 一個可能的解決方案是編輯一些類的原始碼,以便由setter而不是構造器配置。或者,避免建構函式注入,只使用setter注入。換句話說,儘管不建議這樣做,但您可以使用setter注入配置迴圈依賴關係。

Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken/egg scenario).

    • 與典型的情況不同(沒有迴圈依賴關係),bean a和bean B之間的迴圈依賴關係迫使一個bean在完全初始化之前注入另一個bean(典型的先有雞還是先有蛋的場景)。
  • You can generally trust Spring to do the right thing. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time. Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container which has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies. For example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans will lazy-initialize, rather than be pre-instantiated.

    • 您通常可以相信Spring會做正確的事情。它在容器載入時檢測配置問題,例如對不存在的bean的引用和迴圈依賴關係。Spring儘可能晚地設定屬性並解析依賴項,當bean實際建立時。這意味著,當您請求一個物件時,如果在建立該物件或其依賴項時出現問題,已正確載入的Spring容器可以稍後生成一個異常。例如,bean由於缺少或無效的屬性而丟擲異常。這可能會延遲可見性
  • If no circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean. This means that if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A. In other words, the bean is instantiated (if not a pre-instantiated singleton), its dependencies are set, and the relevant lifecycle methods (such as a configured init method or the InitializingBean callback method) are invoked.

    • 如果不存在迴圈依賴關係,那麼當一個或多個協作bean被注入到依賴bean中時,每個協作bean在被注入到依賴bean之前都已被完全配置。這意味著如果bean依賴bean B, B Spring IoC容器完全配置bean之前呼叫bean的setter方法A。換句話說,bean例項化(如果不是一個單例預先例項化),其設定依賴項,相關的生命週期方法(如InitializingBean init方法或配置回撥方法)呼叫
Examples of dependency injection (依賴注入的例子)
  • The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions:
    • 下面的示例對基於setter的DI使用基於xml的配置後設資料。Spring XML配置檔案的一小部分指定了一些bean定義:
<bean id="exampleBean" class="examples.ExampleBean">
    <!-- setter injection using the nested ref element -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- setter injection using the neater ref attribute -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }
}
  • In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI:
    • 在前面的示例中,將setter宣告為與XML檔案中指定的屬性相匹配。下面的例子使用了基於構造器的DI:
<bean id="exampleBean" class="examples.ExampleBean">
    <!-- constructor injection using the nested ref element -->
    <constructor-arg>
        <ref bean="anotherExampleBean"/>
    </constructor-arg>

    <!-- constructor injection using the neater ref attribute -->
    <constructor-arg ref="yetAnotherBean"/>

    <constructor-arg type="int" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

    public ExampleBean(
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        this.beanOne = anotherBean;
        this.beanTwo = yetAnotherBean;
        this.i = i;
    }
}
  • The constructor arguments specified in the bean definition will be used as arguments to the constructor of the ExampleBean.

    • bean定義中指定的建構函式引數將用作ExampleBean建構函式的引數。
  • Now consider a variant of this example, where instead of using a constructor, Spring is told to call a static factory method to return an instance of the object:

    • 現在考慮這個例子的一個變體,這裡不是使用建構函式,而是讓Spring呼叫一個靜態工廠方法來返回一個物件的例項:
<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    // a private constructor
    private ExampleBean(...) {
        ...
    }

    // a static factory method; the arguments to this method can be
    // considered the dependencies of the bean that is returned,
    // regardless of how those arguments are actually used.
    public static ExampleBean createInstance (
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

        ExampleBean eb = new ExampleBean (...);
        // some other operations...
        return eb;
    }
}
  • Arguments to the static factory method are supplied via <constructor-arg/> elements, exactly the same as if a constructor had actually been used. The type of the class being returned by the factory method does not have to be of the same type as the class that contains the static factory method, although in this example it is. An instance (non-static) factory method would be used in an essentially identical fashion (aside from the use of the factory-bean attribute instead of the class attribute), so details will not be discussed here.
    • 靜態工廠方法的引數是通過元素提供的,就像實際使用了建構函式一樣。由工廠方法返回的類的型別不必與包含靜態工廠方法的類的型別相同,儘管在本例中它是相同的。例項(非靜態)工廠方法將以基本相同的方式使用(除了使用factory-bean屬性而不是class屬性之外),因此這裡不討論細
1.4.2. Dependencies and configuration in detail (詳細介紹依賴關係和配置)
  • As mentioned in the previous section, you can define bean properties and constructor arguments as references to other managed beans (collaborators), or as values defined inline. Spring’s XML-based configuration metadata supports sub-element types within its <property/> and <constructor-arg/> elements for this purpose.
    • 如前一節所述,可以將bean屬性和建構函式引數定義為對其他託管bean(協作者)的引用,或者定義為內聯定義的值。Spring基於xml的配置後設資料支援其元素中的子元素型別
Straight values (primitives, Strings, and so on) (直接值【原語、字串等】)
  • The value attribute of the <property/> element specifies a property or constructor argument as a human-readable string representation. Spring’s conversion service is used to convert these values from a String to the actual type of the property or argument.
    • 元素的value屬性將屬性或建構函式引數指定為人類可讀的字串表示形式。Spring的轉換服務用於將這些值從字串轉換為屬性或引數的實際型別
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- results in a setDriverClassName(String) call -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="masterkaoli"/>
</bean>
  • The following example uses the p-namespace for even more succinct XML configuration.
    • 下面的示例使用p-名稱空間進行更簡潔的XML配置。
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/mydb"
        p:username="root"
        p:password="masterkaoli"/>

</beans>
  • The preceding XML is more succinct; however, typos are discovered at runtime rather than design time, unless you use an IDE such as IntelliJ IDEA or the Spring Tool Suite (STS) that support automatic property completion when you create bean definitions. Such IDE assistance is highly recommended.

    • 前面的XML更簡潔;然而,拼寫錯誤是在執行時而不是設計時發現的,除非您使用IDE,如IntelliJ IDEA或Spring工具套件(STS),這些IDE支援在建立bean定義時自動完成屬性。強烈建議提供這樣的IDE幫助。
  • You can also configure a java.util.Properties instance as:

    • 您還可以配置java.util。屬性例項:
<bean id="mappings"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

    <!-- typed as a java.util.Properties -->
    <property name="properties">
        <value>
            jdbc.driver.className=com.mysql.jdbc.Driver
            jdbc.url=jdbc:mysql://localhost:3306/mydb
        </value>
    </property>
</bean>
  • The Spring container converts the text inside the <value/> element into a java.util.Properties instance by using the JavaBeans PropertyEditor mechanism. This is a nice shortcut, and is one of a few places where the Spring team do favor the use of the nested <value/> element over the value attribute style.

    • Spring容器將元素中的文字轉換為java.util。屬性例項,通過使用JavaBeans的PropertyEditor機制。這是一個很好的快捷方式,也是Spring團隊偏愛使用巢狀的元素而不是value屬性styl的幾個地方之一.
  • The idref element

    • idref元素
  • The idref element is simply an error-proof way to pass the id (string value - not a reference) of another bean in the container to a <constructor-arg/> or <property/> element.

    • idref元素只是將容器中另一個bean的id(字串值——而不是引用)傳遞給元素的一種防止錯誤的方法。
<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
    <property name="targetName">
        <idref bean="theTargetBean"/>
    </property>
</bean>
  • The above bean definition snippet is exactly equivalent (at runtime) to the following snippet:
    • 上面的bean定義程式碼片段(在執行時)與下面的程式碼片段完全相同:
<bean id="theTargetBean" class="..." />

<bean id="client" class="...">
    <property name="targetName" value="theTargetBean"/>
</bean>
  • The first form is preferable to the second, because using the idref tag allows the container to validate at deployment time that the referenced, named bean actually exists. In the second variation, no validation is performed on the value that is passed to the targetName property of the client bean. Typos are only discovered (with most likely fatal results) when the client bean is actually instantiated. If the client bean is a prototype bean, this typo and the resulting exception may only be discovered long after the container is deployed.

    • 第一種形式比第二種形式更好,因為使用idref標記允許容器在部署時驗證引用的已命名bean確實存在。在第二個變體中,對傳遞給客戶機bean的targetName屬性的值不執行驗證。只有在實際例項化客戶機bean時才會發現拼寫錯誤(最有可能導致致命的結果)。如果客戶端bean是原型bean,則此型別和結果異常可能要在容器部署很久之後才會被發現。
  • The local attribute on the idref element is no longer supported in the 4.0 beans xsd since it does not provide value over a regular bean reference anymore. Simply change your existing idref local references to idref bean when upgrading to the 4.0 schema.

    • 在4.0 bean xsd中不再支援idref元素上的local屬性,因為它不再提供常規bean引用上的值。只要在升級到4.0模式時將現有的idref本地引用更改為idref bean即可。
  • A common place (at least in versions earlier than Spring 2.0) where the <idref/> element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean bean definition. Using <idref/> elements when you specify the interceptor names prevents you from misspelling an interceptor id.

    • 元素帶來值的常見位置(至少在spring2.0之前的版本中)是在ProxyFactoryBean bean定義中的AOP攔截器配置中。在指定攔截器名稱時使用元素可以防止拼寫錯誤。
References to other beans (collaborators) (對其他bean【協作者】的引用)
  • The ref element is the final element inside a <constructor-arg/> or <property/> definition element. Here you set the value of the specified property of a bean to be a reference to another bean (a collaborator) managed by the container. The referenced bean is a dependency of the bean whose property will be set, and it is initialized on demand as needed before the property is set. (If the collaborator is a singleton bean, it may be initialized already by the container.) All references are ultimately a reference to another object. Scoping and validation depend on whether you specify the id/name of the other object through the bean, local, or parent attributes.

    • ref元素是定義元素中的最後一個元素。在這裡,您將bean的指定屬性的值設定為對容器管理的另一個bean(協作者)的引用。被引用的bean是將被設定其屬性的bean的依賴項,並且在設定屬性之前根據需要對其進行初始化(如果協作者是單例bean,它可能已經被容器初始化了)。所有引用最終都是對另一個物件的引用。範圍和驗證取決於是否指定id/名稱o
  • Specifying the target bean through the bean attribute of the <ref/> tag is the most general form, and allows creation of a reference to any bean in the same container or parent container, regardless of whether it is in the same XML file. The value of the bean attribute may be the same as the id attribute of the target bean, or as one of the values in the name attribute of the target bean.

    • 通過標記的bean屬性指定目標bean是最通用的形式,它允許建立對同一容器或父容器中任何bean的引用,而不管它是否在同一XML檔案中。bean屬性的值可以與目標bean的id屬性相同,或者與目標bean的name屬性中的一個值相同。
<ref bean="someBean"/>
  • Specifying the target bean through the parent attribute creates a reference to a bean that is in a parent container of the current container. The value of the parent attribute may be the same as either the id attribute of the target bean, or one of the values in the name attribute of the target bean, and the target bean must be in a parent container of the current one. You use this bean reference variant mainly when you have a hierarchy of containers and you want to wrap an existing bean in a parent container with a proxy that will have the same name as the parent bean.
    • 通過父屬性指定目標bean,將建立對當前容器父容器中bean的引用。父屬性的值可以與目標bean的id屬性相同,或者與目標bean的name屬性中的一個值相同,並且目標bean必須位於當前容器的父容器中。當您擁有容器的層次結構並且希望使用與父bean同名的代理將現有bean包裝在父容器中時,您主要會使用此bean引用變數
<!-- in the parent context -->
<bean id="accountService" class="com.foo.SimpleAccountService">
    <!-- insert dependencies as required as here -->
</bean>
<!-- in the child (descendant) context -->
<bean id="accountService" <!-- bean name is the same as the parent bean -->
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
        <ref parent="accountService"/> <!-- notice how we refer to the parent bean -->
    </property>
    <!-- insert other configuration and dependencies as required here -->
</bean>
  • The local attribute on the ref element is no longer supported in the 4.0 beans xsd since it does not provide value over a regular bean reference anymore. Simply change your existing ref local references to ref bean when upgrading to the 4.0 schema.
    • 在4.0 bean xsd中不再支援ref元素上的local屬性,因為它不再提供常規bean引用上的值。只要在升級到4.0模式時將現有的ref本地引用更改為ref bean即可。
Inner beans (內部beans)
  • A <bean/> element inside the <property/> or <constructor-arg/> elements defines a so-called inner bean.
    • 元素中的元素定義了一個所謂的內部bean。
<bean id="outer" class="...">
    <!-- instead of using a reference to a target bean, simply define the target bean inline -->
    <property name="target">
        <bean class="com.example.Person"> <!-- this is the inner bean -->
            <property name="name" value="Fiona Apple"/>
            <property name="age" value="25"/>
        </bean>
    </property>
</bean>
  • An inner bean definition does not require a defined id or name; if specified, the container does not use such a value as an identifier. The container also ignores the scope flag on creation: Inner beans are always anonymous and they are always created with the outer bean. It is not possible to inject inner beans into collaborating beans other than into the enclosing bean or to access them independently.

    • 內部bean定義不需要定義id或名稱;如果指定,容器不使用這樣的值作為識別符號。容器在建立時還會忽略scope標誌:內部bean始終是匿名的,並且始終是用外部bean建立的。除了將內部bean注入到封裝bean中之外,不可能將內部bean注入到協作bean中,也不可能獨立地訪問它們。
  • As a corner case, it is possible to receive destruction callbacks from a custom scope, e.g. for a request-scoped inner bean contained within a singleton bean: The creation of the inner bean instance will be tied to its containing bean, but destruction callbacks allow it to participate in the request scope’s lifecycle. This is not a common scenario; inner beans typically simply share their containing bean’s scope.

    • 角情況下,可以接收來自自定義範圍的破壞回撥,例如請求範圍內內在bean包含在一個單例bean:內心的bean例項的建立將繫結到包含bean,但破壞回撥允許它參與請求範圍的生命週期。這不是常見的場景;內部bean通常只是共享包含它們的bean的作用域。
Collections (集合)
  • In the <list/>, <set/>, <map/>, and <props/> elements, you set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively.
    • 元素中,您可以分別設定Java集合型別列表、set、map和properties的屬性和引數。
<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>
  • The value of a map key or value, or a set value, can also again be any of the following elements:
    • 對映鍵或值的值,或設定值,也可以是以下任何元素:
bean | ref | idref | list | set | map | props | value | null
  • Collection merging

    • 收集合並
  • The Spring container also supports the merging of collections. An application developer can define a parent-style , , or element, and have child-style , , or elements inherit and override values from the parent collection. That is, the child collection’s values are the result of merging the elements of the parent and child collections, with the child’s collection elements overriding values specified in the parent collection.

    • Spring容器還支援集合的合併。應用開發者可以定義父樣式元素,讓子樣式元素繼承和覆蓋父集合的值。也就是說,子集合的值是合併父集合和子集合的元素的結果,子集合元素覆蓋父集合中指定的值。
  • This section on merging discusses the parent-child bean mechanism. Readers unfamiliar with parent and child bean definitions may wish to read the relevant section before continuing.

    • 關於合併的這一節討論父-子bean機制。不熟悉父bean和子bean定義的讀者可能希望在繼續之前閱讀相關部分。
  • The following example demonstrates collection merging:

    • 下面的例子演示了集合合併:
<beans>
    <bean id="parent" abstract="true" class="example.ComplexObject">
        <property name="adminEmails">
            <props>
                <prop key="administrator">administrator@example.com</prop>
                <prop key="support">support@example.com</prop>
            </props>
        </property>
    </bean>
    <bean id="child" parent="parent">
        <property name="adminEmails">
            <!-- the merge is specified on the child collection definition -->
            <props merge="true">
                <prop key="sales">sales@example.com</prop>
                <prop key="support">support@example.co.uk</prop>
            </props>
        </property>
    </bean>
<beans>
  • Notice the use of the merge=true attribute on the <props/> element of the adminEmails property of the child bean definition. When the child bean is resolved and instantiated by the container, the resulting instance has an adminEmails Properties collection that contains the result of the merging of the child’s adminEmails collection with the parent’s adminEmails collection.
    • 注意在子bean定義的adminEmails屬性的元素上使用了merge=true屬性。當容器解析並例項化子bean時,生成的例項具有一個adminEmails屬性集合,其中包含子例項的adminEmails集合與父例項的adminEmails集合合併的結果。
administrator=administrator@example.com
sales=sales@example.com
support=support@example.co.uk
  • The child Properties collection’s value set inherits all property elements from the parent <props/>, and the child’s value for the support value overrides the value in the parent collection.

    • 子屬性集合的值集繼承父屬性中的所有屬性元素,子屬性支援值的值覆蓋父屬性集合中的值。
  • This merging behavior applies similarly to the <list/>, <map/>, and <set/> collection types. In the specific case of the <list/> element, the semantics associated with the List collection type, that is, the notion of an ordered collection of values, is maintained; the parent’s values precede all of the child list’s values. In the case of the Map, Set, and Properties collection types, no ordering exists. Hence no ordering semantics are in effect for the collection types that underlie the associated Map, Set, and Properties implementation types that the container uses internally.

    • 這種合併行為類似地應用於集合型別。在元素的特定情況下,維護與列表集合型別相關的語義,即值的有序集合的概念;父元素的值位於所有子元素列表的值之前。對於Map、Set和Properties集合型別,不存在排序。因此,對於位於容器內部使用的關聯對映、集合和屬性實現型別下的集合型別,排序語義不起作用。
  • Limitations of collection merging

    • 集合合併的限制
  • You cannot merge different collection types (such as a Map and a List), and if you do attempt to do so an appropriate Exception is thrown. The merge attribute must be specified on the lower, inherited, child definition; specifying the merge attribute on a parent collection definition is redundant and will not result in the desired merging.

    • 您不能合併不同的集合型別(如對映和列表),如果您嘗試這樣做,將引發適當的異常。merge屬性必須在較低的繼承子定義中指定;在父集合定義上指定合併屬性是多餘的,不會導致所需的合併。
  • Strongly-typed collection

    • 強型別集合
  • With the introduction of generic types in Java 5, you can use strongly typed collections. That is, it is possible to declare a Collection type such that it can only contain String elements (for example). If you are using Spring to dependency-inject a strongly-typed Collection into a bean, you can take advantage of Spring’s type-conversion support such that the elements of your strongly-typed Collection instances are converted to the appropriate type prior to being added to the Collection.

    • 隨著Java 5中泛型型別的引入,您可以使用強型別集合。也就是說,可以宣告一個集合型別,使它只能包含字串元素(例如)。如果您使用Spring將依賴注入強型別集合到bean中,那麼您可以利用Spring的型別轉換支援,這樣強型別集合例項的元素在新增到集合之前會被轉換為適當的型別。
public class Foo {

    private Map<String, Float> accounts;

    public void setAccounts(Map<String, Float> accounts) {
        this.accounts = accounts;
    }
}
<beans>
    <bean id="foo" class="x.y.Foo">
        <property name="accounts">
            <map>
                <entry key="one" value="9.99"/>
                <entry key="two" value="2.75"/>
                <entry key="six" value="3.99"/>
            </map>
        </property>
    </bean>
</beans>
  • When the accounts property of the foo bean is prepared for injection, the generics information about the element type of the strongly-typed Map<String, Float> is available by reflection. Thus Spring’s type conversion infrastructure recognizes the various value elements as being of type Float, and the string values 9.99, 2.75, and 3.99 are converted into an actual Float type.
    • 當foo bean的accounts屬性為注入做好準備時,關於強型別Map<String, Float>的元素型別的泛型資訊可以通過反射獲得。因此,Spring的型別轉換基礎設施將各種值元素識別為Float型別,並將字串值9.99、2.75和3.99轉換為實際的Float型別。
Null and empty string values (Null和空字串值)
  • Spring treats empty arguments for properties and the like as empty Strings. The following XML-based configuration metadata snippet sets the email property to the empty String value ("").
    • Spring將屬性之類的空引數視為空字串。以下基於xml的配置後設資料片段將email屬性設定為空字串值("")。
<bean class="ExampleBean">
    <property name="email" value=""/>
</bean>
  • The preceding example is equivalent to the following Java code:
    • 前面的例子相當於下面的Java程式碼:
exampleBean.setEmail("");
  • The <null/> element handles null values. For example:
    • 元素的作用是:處理空值。為
<bean class="ExampleBean">
    <property name="email">
        <null/>
    </property>
</bean>
  • The above configuration is equivalent to the following Java code:
    • 上面的配置相當於下面的Java程式碼
exampleBean.setEmail(null);
XML shortcut with the p-namespace (帶有p-名稱空間的XML快捷方式)
  • The p-namespace enables you to use the bean element’s attributes, instead of nested <property/> elements, to describe your property values and/or collaborating beans.

    • p-名稱空間使您能夠使用bean元素的屬性(而不是巢狀的元素)來描述您的屬性值和/或協作bean。
  • Spring supports extensible configuration formats with namespaces, which are based on an XML Schema definition. The beans configuration format discussed in this chapter is defined in an XML Schema document. However, the p-namespace is not defined in an XSD file and exists only in the core of Spring.

    • Spring支援帶有名稱空間的可擴充套件配置格式,名稱空間基於XML模式定義。本章中討論的bean配置格式是在XML模式文件中定義的。但是,p-名稱空間沒有在XSD檔案中定義,只存在於Spring的核心中。
  • The following example shows two XML snippets that resolve to the same result: The first uses standard XML format and the second uses the p-namespace.

    • 下面的示例顯示瞭解析為相同結果的兩個XML片段:第一個使用標準XML格式,第二個使用p-名稱空間。
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean name="classic" class="com.example.ExampleBean">
        <property name="email" value="foo@bar.com"/>
    </bean>

    <bean name="p-namespace" class="com.example.ExampleBean"
        p:email="foo@bar.com"/>
</beans>
  • The example shows an attribute in the p-namespace called email in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the p-namespace does not have a schema definition, so you can set the name of the attribute to the property name.

    • 該示例顯示了bean定義中p-名稱空間中名為email的屬性。這告訴Spring包含一個屬性宣告。如前所述,p-namespace沒有模式定義,因此可以將屬性名設定為屬性名。
  • This next example includes two more bean definitions that both have a reference to another bean:

    • 下一個示例包括另外兩個bean定義,它們都引用了另一個be
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean name="john-classic" class="com.example.Person">
        <property name="name" value="John Doe"/>
        <property name="spouse" ref="jane"/>
    </bean>

    <bean name="john-modern"
        class="com.example.Person"
        p:name="John Doe"
        p:spouse-ref="jane"/>

    <bean name="jane" class="com.example.Person">
        <property name="name" value="Jane Doe"/>
    </bean>
</beans>
  • As you can see, this example includes not only a property value using the p-namespace, but also uses a special format to declare property references. Whereas the first bean definition uses <property name="spouse" ref="jane"/> to create a reference from bean john to bean jane, the second bean definition uses p:spouse-ref="jane" as an attribute to do the exact same thing. In this case spouse is the property name, whereas the -ref part indicates that this is not a straight value but rather a reference to another bean.

    • 如您所見,這個示例不僅包含使用p-名稱空間的屬性值,而且還使用一種特殊格式來宣告屬性引用。第一個bean定義使用來建立一個從bean john到bean jane的引用,第二個bean定義使用p:配偶-ref="jane"作為一個屬性來完成完全相同的工作。在本例中,spouse是屬性名,而-ref部分表明這不是一個直接的值,而是對另一個bean的引用。
  • The p-namespace is not as flexible as the standard XML format. For example, the format for declaring property references clashes with properties that end in Ref, whereas the standard XML format does not. We recommend that you choose your approach carefully and communicate this to your team members, to avoid producing XML documents that use all three approaches at the same time.

    • p-名稱空間不如標準XML格式靈活。例如,宣告屬性引用的格式與以Ref結尾的屬性衝突,而標準XML格式不會。我們建議您仔細選擇您的方法,並與您的團隊成員溝通,以避免同時生成使用所有三種方法的XML文件。
XML shortcut with the c-namespace (使用c-名稱空間的XML)
  • Similar to the XML shortcut with the p-namespace, the c-namespace, newly introduced in Spring 3.1, allows usage of inlined attributes for configuring the constructor arguments rather then nested constructor-arg elements.

    • 與p-namespace的XML快捷方式類似,Spring 3.1中新引入的c-namespace允許使用內聯屬性來配置建構函式引數,而不是使用巢狀的建構函式引數元素。
  • Let’s review the examples from Constructor-based dependency injection with the c: namespace:

    • 讓我們回顧一下使用c:名稱空間進行基於構造器的依賴注入的例子:
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="bar" class="x.y.Bar"/>
    <bean id="baz" class="x.y.Baz"/>

    <!-- traditional declaration -->
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/>
        <constructor-arg ref="baz"/>
        <constructor-arg value="foo@bar.com"/>
    </bean>

    <!-- c-namespace declaration -->
    <bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="foo@bar.com"/>

</beans>
  • The c: namespace uses the same conventions as the p: one (trailing -ref for bean references) for setting the constructor arguments by their names. And just as well, it needs to be declared even though it is not defined in an XSD schema (but it exists inside the Spring core).

    • 名稱空間使用與p: one相同的約定(對於bean引用,尾隨-ref)來按名稱設定建構函式引數。同樣,即使它沒有在XSD模式中定義(但它存在於Spring核心中),也需要宣告它。
  • For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), one can use fallback to the argument indexes:

    • 對於建構函式引數名不可用的罕見情況(通常是在編譯位元組碼時沒有除錯資訊),可以使用回退到引數索引:
<!-- c-namespace index declaration -->
<bean id="foo" class="x.y.Foo" c:_0-ref="bar" c:_1-ref="baz"/>
  • Due to the XML grammar, the index notation requires the presence of the leading _ as XML attribute names cannot start with a number (even though some IDE allow it).

    • 由於XML語法的原因,索引表示法要求出現前導_,因為XML屬性名不能以數字開頭(儘管一些IDE允許這樣做)。
  • In practice, the constructor resolution mechanism is quite efficient in matching arguments so unless one really needs to, we recommend using the name notation through-out your configuration.

    • 在實踐中,建構函式解析機制在匹配引數方面非常有效,因此,除非確實需要,我們建議在整個配置中使用名稱符號。
Compound property names (複合屬性名)
  • You can use compound or nested property names when you set bean properties, as long as all components of the path except the final property name are not null. Consider the following bean definition.
    • 在設定bean屬性時,可以使用複合或巢狀屬性名,只要路徑的所有元件(最終屬性名除外)不為空。考慮下面的bean定義。
<bean id="foo" class="foo.Bar">
    <property name="fred.bob.sammy" value="123" />
</bean>
  • The foo bean has a fred property, which has a bob property, which has a sammy property, and that final sammy property is being set to the value 123. In order for this to work, the fred property of foo, and the bob property of fred must not be null after the bean is constructed, or a NullPointerException is thrown.
    • foo bean有一個fred屬性,這個fred屬性有一個bob屬性,這個bob屬性又有一個sammy屬性,最後一個sammy屬性被設定為123。為了使其工作,在構造bean之後,foo的fred屬性和fred的bob屬性不能為空,或者丟擲NullPointerException。
1.4.3. Using depends-on (使用取決於)
  • If a bean is a dependency of another that usually means that one bean is set as a property of another. Typically you accomplish this with the `` element in XML-based configuration metadata. However, sometimes dependencies between beans are less direct; for example, a static initializer in a class needs to be triggered, such as database driver registration. The depends-on attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized. The following example uses the depends-on attribute to express a dependency on a single bean:
    • 如果一個bean是另一個bean的依賴項,這通常意味著一個bean被設定為另一個bean的屬性。通常使用基於xml的配置後設資料中的元素來完成此任務。然而,有時bean之間的依賴關係並不那麼直接;例如,類中的靜態初始化器需要被觸發,比如資料庫驅動程式註冊。depends-on屬性可以顯式地強制在初始化使用此元素的bean之前初始化一個或多個bean。下面的例子使用依賴屬性來表示對單個bean的依賴:
<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />
  • To express a dependency on multiple beans, supply a list of bean names as the value of the depends-on attribute, with commas, whitespace and semicolons, used as valid delimiters:
    • 為了表示對多個bean的依賴,提供一個bean名稱列表作為depends-on屬性的值,使用逗號、空格和分號作為有效的分隔符:
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
  • The depends-on attribute in the bean definition can specify both an initialization time dependency and, in the case of singleton beans only, a corresponding destroy time dependency. Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus depends-on can also control shutdown order.
    • bean定義中的depends-on屬性既可以指定初始化時間依賴項,也可以指定對應的銷燬時間依賴項(僅在單例bean中)。在銷燬給定bean本身之前,首先銷燬與給定bean定義依賴關係的依賴bean。因此,依賴還可以控制關機順序。
1.4.4. Lazy-initialized beans (延遲初始化的bean)
  • By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup.

    • 預設情況下,作為初始化過程的一部分,ApplicationContext實現會急切地建立和配置所有的單例bean。通常,這種預例項化是可取的,因為配置或周圍環境中的錯誤是立即發現的,而不是幾小時甚至幾天後發現的。如果不希望出現這種行為,可以通過將bean定義標記為延遲初始化來防止單例bean的預例項化。延遲初始化的bean告訴IoC容器在第一次請求bean例項時(而不是在啟動時)建立bean例項。
  • In XML, this behavior is controlled by the lazy-init attribute on the <bean/> element; for example:

    • 在XML中,這種行為由元素的lazy-init屬性控制;例如:
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.foo.AnotherBean"/>
  • When the preceding configuration is consumed by an ApplicationContext, the bean named lazy is not eagerly pre-instantiated when the ApplicationContext is starting up, whereas the not.lazy bean is eagerly pre-instantiated.

    • 當ApplicationContext使用前面的配置時,在ApplicationContext啟動時,名為lazy的bean不會急於預例項化,而不是。惰性bean被急切地預例項化。
  • However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy-initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized.

    • 然而,當延遲初始化bean是未延遲初始化的單例bean的依賴項時,ApplicationContext在啟動時建立延遲初始化bean,因為它必須滿足單例的依賴項。惰性初始化的bean被注入到沒有惰性初始化的其他地方的單例bean中。
  • You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the <beans/> element; for example:

    • 通過使用元素上的default-lazy-init屬性,還可以在容器級別控制延遲初始化;例如:
<beans default-lazy-init="true">
    <!-- no beans will be pre-instantiated... -->
</beans>
1.4.5. Autowiring collaborators (自動裝配的合作者)
  • The Spring container can autowire relationships between collaborating beans. You can allow Spring to resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext. Autowiring has the following advantages:

    • Spring容器可以自動連線協作bean之間的關係。通過檢查ApplicationContext的內容,您可以允許Spring為您的bean自動解析協作者(其他bean)。自動裝配有以下優點:
  • Autowiring can significantly reduce the need to specify properties or constructor arguments. (Other mechanisms such as a bean template discussed elsewhere in this chapter are also valuable in this regard.)

    • 自動裝配可以顯著減少指定屬性或建構函式引數的需要。(其他機制,比如本章其他地方討論的bean模板,在這方面也很有價值。)
  • Autowiring can update a configuration as your objects evolve. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to modify the configuration. Thus autowiring can be especially useful during development, without negating the option of switching to explicit wiring when the code base becomes more stable.

    • 自動裝配可以隨著物件的發展更新配置。例如,如果需要向類新增依賴項,則無需修改配置即可自動滿足該依賴項。因此,自動裝配在開發過程中特別有用,當程式碼庫變得更加穩定時,無需切換到顯式連線。
  • When using XML-based configuration metadata [2], you specify autowire mode for a bean definition with the autowire attribute of the <bean/> element. The autowiring functionality has four modes. You specify autowiring per bean and thus can choose which ones to autowire.

    • 當使用基於xml的配置後設資料[2]時,您可以使用元素的autowire屬性為bean定義指定自動裝配模式。自動裝配功能有四種模式。您可以為每個bean指定自動裝配,因此可以選擇要自動裝配的bean。
  • Table 2. Autowiring modes (自動裝配模式)

Mode(模式) Explanation(說明)
no(無) (Default) No autowiring. Bean references must be defined via a ref element. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system.((預設)沒有自動裝配。Bean引用必須通過ref元素定義。對於較大的部署,不建議更改預設設定,因為顯式地指定collaborator可以提供更好的控制和清晰度。在某種程度上,它記錄了系統的結構。)
byName(按名稱裝配) Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name, and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master, and uses it to set the property.(按屬性名稱自動裝配。Spring尋找與需要自動實現的屬性同名的bean。例如,如果一個bean定義按名稱設定為autowire,並且它包含一個master屬性(也就是說,它有一個setMaster(..)方法),那麼Spring將查詢一個名為master的bean定義,並使用它來設定該屬性。)
byType(按型別裝配) Allows a property to be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens; the property is not set.(如果容器中恰好存在該屬性型別的一個bean,則允許該屬性被自動呼叫。如果存在多個,就會丟擲一個致命異常,這表明您不能對該bean使用byType自動裝配。如果沒有匹配的豆子,什麼也不會發生;該屬性未設定。)
constructor(構造器裝配) Analogous to byType, but applies to constructor arguments. If there is not exactly one bean of the constructor argument ty(類似於byType,但適用於建構函式引數。如果容器中沒有建構函式引數型別的確切bean,就會引發致命錯誤。)
  • With byType or constructor autowiring mode, you can wire arrays and typed-collections. In such cases all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Maps if the expected key type is String. An autowired Maps values will consist of all bean instances that match the expected type, and the Maps keys will contain the corresponding bean names.

  • 使用byType或建構函式自動裝配模式,您可以連線陣列和型別集合。在這種情況下,將提供容器中與預期型別匹配的所有自動裝配候選物件來滿足依賴關係。如果期望的鍵型別是String,你可以自動連線強型別的對映。自動生成的Maps值將由與預期型別匹配的所有bean例項組成,Maps鍵將包含相應的bean名稱。

  • You can combine autowire behavior with dependency checking, which is performed after autowiring completes.

    您可以將自動裝配行為與依賴項檢查結合起來,依賴項檢查是在自動裝配完成後執行的。

    Limitations and disadvantages of autowiring (自動裝配的侷限性和缺點)
  • Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions.

  • 自動裝配在專案中一致使用時工作得最好。如果自動裝配沒有被普遍使用,那麼使用它來連線一個或兩個bean定義可能會使開發人員感到困惑。

  • Consider the limitations and disadvantages of autowiring:

  • 考慮自動裝配的侷限性和缺點:

  • Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire so-called simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.

    • 屬性和構造引數設定中的顯式依賴關係總是覆蓋自動裝配。您不能自動裝配所謂的簡單屬性,如原語、字串和類(以及此類簡單屬性的陣列)。這種限制是設計出來的。
  • Autowiring is less exact than explicit wiring. Although, as noted in the above table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly.

    • 自動裝配不如顯式佈線精確。儘管如上表中所述,Spring小心地避免猜測可能會產生意外結果的歧義,但是Spring管理物件之間的關係不再被明確地記錄。
  • Wiring information may not be available to tools that may generate documentation from a Spring container.

    • 連線資訊對於可能從Spring容器生成文件的工具來說可能是不可用的
  • Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Maps, this is not necessarily a problem. However for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown.

  • 容器中的多個bean定義可能與要自動實現的setter方法或建構函式引數指定的型別相匹配。對於陣列、集合或對映,這不一定是個問題。但是,對於期望單個值的依賴項,這種模糊性不能任意解決。如果沒有可用的唯一bean定義,則丟擲異常。

  • In the latter scenario, you have several options:

  • 在後一種情況下,您有幾個選項:

  • Abandon autowiring in favor of explicit wiring.

    • 放棄自動裝配,支援顯式佈線。
  • Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false as described in the next section.

    • 通過將一個bean定義的自動裝配候選屬性設定為false來避免自動裝配,如下一節所述。
  • Designate a single bean definition as the primary candidate by setting the primary attribute of its <bean/> element to true.

    • 通過將單個bean定義的元素的主屬性設定為true,將其指定為主候選bean定義。
  • Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based container configuration.

    • 使用基於註釋的配置實現更細粒度的控制,如在基於註釋的容器配置中所述。
Excluding a bean from autowiring(不包括自動裝配的bean)
  • On a per-bean basis, you can exclude a bean from autowiring. In Spring’s XML format, set the autowire-candidate attribute of the <bean/> element to false; the container makes that specific bean definition unavailable to the autowiring infrastructure (including annotation style configurations such as @Autowired).

    • 在每個bean的基礎上,您可以從自動裝配中排除一個bean。在Spring的XML格式中,將元素的autowell -candidate屬性設定為false;容器使得特定的bean定義對自動裝配基礎設施不可用(包括註釋風格配置,如@Autowired)。
  • The autowire-candidate attribute is designed to only affect type-based autowiring. It does not affect explicit references by name, which will get resolved even if the specified bean is not marked as an autowire candidate. As a consequence, autowiring by name will nevertheless inject a bean if the name matches.

    • autowire-candidate屬性被設計為隻影響基於型別的自動裝配。它不會影響名稱的顯式引用,即使指定的bean沒有標記為自動裝配候選物件,也會被解析。因此,如果名稱匹配,按名稱自動裝配仍然會注入一個bean。
  • You can also limit autowire candidates based on pattern-matching against bean names. The top-level <beans/> element accepts one or more patterns within its default-autowire-candidates attribute. For example, to limit autowire candidate status to any bean whose name ends with Repository, provide a value of *Repository. To provide multiple patterns, define them in a comma-separated list. An explicit value of true or false for a bean definitions autowire-candidate attribute always takes precedence, and for such beans, the pattern matching rules do not apply.

    • 您還可以基於對bean名稱的模式匹配來限制自動連線候選項。頂級的元素在其預設-自動連線-候選屬性中接受一個或多個模式。例如,要將自動裝配候選狀態限制為名稱以Repository結尾的任何bean,可以提供一個值*Repository。要提供多個模式,請在逗號分隔的列表中定義它們。bean定義自動候選屬性的顯式值true或false總是優先,對於這樣的bean,模式匹配規則不適用。
  • These techniques are useful for beans that you never want to be injected into other beans by autowiring. It does not mean that an excluded bean cannot itself be configured using autowiring. Rather, the bean itself is not a candidate for autowiring other beans.

    • 這些技術對於那些您永遠不希望通過自動裝配被注入到其他bean中的bean非常有用。這並不意味著被排除的bean本身不能使用自動裝配進行配置。相反,該bean本身不是自動連線其他bean的候選物件。
1.4.6. Method injection (方法注射)
  • In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean, or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container only creates the singleton bean A once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed.

    • 在大多數應用程式場景中,容器中的大多數bean都是單例的。當一個單例bean需要與另一個單例bean協作時,或者一個非單例bean需要與另一個非單例bean協作時,通常通過將一個bean定義為另一個bean的屬性來處理依賴關係。當bean的生命週期不同時,問題就出現了。假設單例bean A需要使用非單例(原型)bean B,可能在對A的每次方法呼叫上都是如此,容器只建立單例bean A一次,因此只有一次機會設定屬性。的帳目
  • A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following is an example of this approach:

    • 一個解決辦法是放棄一些控制反轉。您可以通過實現applicationcontexts taware介面,以及在每次bean A需要bean B例項時,通過對容器進行getBean(“B”)呼叫來讓bean A知道容器。下面是這種方法的一個例子:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;

// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public Object process(Map commandState) {
        // grab a new instance of the appropriate Command
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    protected Command createCommand() {
        // notice the Spring API dependency!
        return this.applicationContext.getBean("command", Command.class);
    }

    public void setApplicationContext(
            ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
  • The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, allows this use case to be handled in a clean fashion.
    • 前面的方法並不可取,因為業務程式碼知道Spring框架並與之耦合。方法注入是Spring IoC容器的一種高階特性,它允許以一種乾淨的方式處理此用例。

You can read more about the motivation for Method Injection in this blog entry.

    • 您可以在這篇部落格文章中閱讀更多關於方法注入動機的內容。
Lookup method injection (查詢方法注入)
  • Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container. The lookup typically involves a prototype bean as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to generate dynamically a subclass that overrides the method.

    • 查詢方法注入是指容器覆蓋容器管理bean上的方法,返回容器中另一個已命名bean的查詢結果的能力。查詢通常涉及原型bean,如上一節所述的場景。Spring框架通過使用來自CGLIB庫的位元組碼生成動態地生成覆蓋該方法的子類來實現這種方法注入。
  • For this dynamic subclassing to work, the class that the Spring bean container will subclass cannot be final, and the method to be overridden cannot be final either.

    • 要使這個動態子類工作,Spring bean容器將子類化的類不能是final,被覆蓋的方法也不能是final。
  • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.

    • 單元測試具有抽象方法的類需要您自己建立類的子類,並提供抽象方法的存根實現。
  • Concrete methods are also necessary for component scanning which requires concrete classes to pick up.

    • Concrete methods are also necessary for component scanning which requires concrete classes to pick up.
  • A further key limitation is that lookup methods won’t work with factory methods and in particular not with @Bean methods in configuration classes, since the container is not in charge of creating the instance in that case and therefore cannot create a runtime-generated subclass on the fly.

    • 另一個關鍵的限制是,查詢方法不能與工廠方法一起工作,特別是與配置類中的@Bean方法一起工作,因為在這種情況下容器不負責建立例項,因此不能動態地建立執行時生成的子類。
  • Looking at the CommandManager class in the previous code snippet, you see that the Spring container will dynamically override the implementation of the createCommand() method. Your CommandManager class will not have any Spring dependencies, as can be seen in the reworked example:

    • 檢視前面程式碼片段中的CommandManager類,您可以看到Spring容器將動態覆蓋createCommand()方法的實現。你的CommandManager類將沒有任何Spring依賴項,就像在重寫的例子中看到的那樣:
package fiona.apple;

// no more Spring imports!

public abstract class CommandManager {

    public Object process(Object commandState) {
        // grab a new instance of the appropriate Command interface
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    // okay... but where is the implementation of this method?
    protected abstract Command createCommand();
}
  • In the client class containing the method to be injected (the CommandManager in this case), the method to be injected requires a signature of the following form:
    • 在包含要注入的方法的客戶端類中(本例中為CommandManager),要注入的方法需要以下形式的簽名:
<public|protected> [abstract] <return-type> theMethodName(no-arguments);
  • If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. For example:
    • 如果方法是抽象的,則動態生成的子類實現該方法。否則,動態生成的子類將覆蓋在原始類中定義的具體方法。例如:
<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype">
    <!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
    <lookup-method name="createCommand" bean="myCommand"/>
</bean>
  • The bean identified as commandManager calls its own method createCommand() whenever it needs a new instance of the myCommand bean. You must be careful to deploy the myCommand bean as a prototype, if that is actually what is needed. If it is as a singleton, the same instance of the myCommand bean is returned each time.

    • 標識為commandManager的bean在需要myCommand bean的新例項時呼叫自己的方法createCommand()。如果真的需要將myCommand bean部署為原型,則必須小心。如果它是單例的,那麼每次都返回相同的myCommand bean例項。
  • Alternatively, within the annotation-based component model, you may declare a lookup method through the @Lookup annotation:

    • 或者,在基於註釋的元件模型中,您可以通過@Lookup註釋宣告一個查詢方法:
public abstract class CommandManager {

    public Object process(Object commandState) {
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup("myCommand")
    protected abstract Command createCommand();
}
  • Or, more idiomatically, you may rely on the target bean getting resolved against the declared return type of the lookup method:
    • 或者,更習慣地說,你可以依賴於目標bean來解析查詢方法宣告的返回型別:
public abstract class CommandManager {

    public Object process(Object commandState) {
        MyCommand command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup
    protected abstract MyCommand createCommand();
}
  • Note that you will typically declare such annotated lookup methods with a concrete stub implementation, in order for them to be compatible with Spring’s component scanning rules where abstract classes get ignored by default. This limitation does not apply in case of explicitly registered or explicitly imported bean classes.

  • 請注意,您通常會使用具體的存根實現來宣告這種帶註釋的查詢方法,以便它們與Spring的元件掃描規則相容,其中抽象類在預設情況下會被忽略。此限制不適用於顯式註冊或顯式匯入的bean類。

  • Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. Check out Scoped beans as dependencies.

    The interested reader may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be of use.

    • 訪問作用域不同的目標bean的另一種方法是ObjectFactory/ Provider注入點。檢出作用域bean作為依賴項。

      感興趣的讀者還可以在org.springframework.beans.factory中找到ServiceLocatorFactoryBean。配置包)的使用。

Arbitrary method replacement (任意的方法替換)
  • A less useful form of method injection than lookup method injection is the ability to replace arbitrary methods in a managed bean with another method implementation. Users may safely skip the rest of this section until the functionality is actually needed.

    • 方法注入的一種不如查詢方法注入有用的形式是用另一個方法實現替換託管bean中的任意方法的能力。使用者可以跳過本節的其餘部分,直到真正需要這些功能。
  • With XML-based configuration metadata, you can use the replaced-method element to replace an existing method implementation with another, for a deployed bean. Consider the following class, with a method computeValue, which we want to override:

    • 對於基於xml的配置後設資料,您可以使用replaced-method元素將一個已部署bean的現有方法實現替換為另一個方法實現。考慮下面的類,帶有一個方法computeValue,我們想要覆蓋它:
public class MyValueCalculator {

    public String computeValue(String input) {
        // some real code...
    }

    // some other methods...
}
  • A class implementing the org.springframework.beans.factory.support.MethodReplacer interface provides the new method definition.
    • 實現org.springframework.bean .factory.support的類。MethodReplacer介面提供了新的方法定義。
/**
 * meant to be used to override the existing computeValue(String)
 * implementation in MyValueCalculator
 */
public class ReplacementComputeValue implements MethodReplacer {

    public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
        // get the input value, work with it, and return a computed result
        String input = (String) args[0];
        ...
        return ...;
    }
}
  • The bean definition to deploy the original class and specify the method override would look like this:
    • 部署原始類並指定方法覆蓋的bean定義如下:
<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
    <!-- arbitrary method replacement -->
    <replaced-method name="computeValue" replacer="replacementComputeValue">
        <arg-type>String</arg-type>
    </replaced-method>
</bean>

<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>
  • You can use one or more contained <arg-type/> elements within the <replaced-method/> element to indicate the method signature of the method being overridden. The signature for the arguments is necessary only if the method is overloaded and multiple variants exist within the class. For convenience, the type string for an argument may be a substring of the fully qualified type name. For example, the following all match java.lang.String:
    • 可以使用元素中包含的一個或多個< argtype />元素來指示被覆蓋方法的方法簽名。只有當方法被過載並且類中存在多個變體時,引數的簽名才有必要。為了方便,引數的型別字串可以是完全限定型別名的子字串。例如,以下所有匹配java.lang.String:
java.lang.String
String
Str
  • Because the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by allowing you to type only the shortest string that will match an argument type.
    • 由於引數的數量通常足以區分每種可能的選擇,因此通過只鍵入與引數型別匹配的最短字串,此快捷方式可以節省大量輸入。

後續翻譯玩命載入中...

相關文章