1.3 Bean概述

官方英文版地址:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html

备注:翻译如有不对,请多指正,谢谢。

 

1.3. Bean overview

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格式<bean/>定义的方式。

 

Within the container itself, these bean definitions are represented as BeanDefinition objects, which contain (among other information) the following metadata:

  • A package-qualified class name: typically the actual implementation class of the bean being defined.

  • Bean behavioral configuration elements, which state how the bean should behave in the container (scope, lifecycle callbacks, and so forth).

  • References to other beans that are needed for the bean to do its work; these references are also called collaborators or dependencies.

  • 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定义并标识成BeanDefinition对象,这些BeanDefinition对象包含如下元数据信息:

  • 一个包名限定的类名:被定义Bean对象的实现类;
  • Bean的行为配置元素,即bean在容器中表现为什么样的状态(范围、生命周期回调等等);
  • Bean自身工作所需要的其他Bean引用,这些引用被称之为协作者或者依赖项;
  • 在新创建对象中的其他配置设置,例如,在连接池管理的Bean中的连接数量或者池的最大限制;

 

This metadata translates to a set of properties that make up each bean definition.

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

 

Table 1. The bean definition
PropertyExplained in…​

class

Instantiating beans

name

Naming beans

scope

Bean scopes

constructor arguments

Dependency Injection

properties

Dependency Injection

autowiring mode

Autowiring collaborators

lazy-initialization mode

Lazy-initialized beans

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的实现类还允许用户注册在容器之外创建的已有对象。这是通过访问ApplicationContext的getBeanFactory方法获取的BeanFactory对象实现的,默认实现是DefaultListableBeanFacory。DefaultListableBeanFactory支持通过registerSingleton()方法和registerBeanDefinition()来完成注册。但是,一般应用程序只使用通过元数据定义的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

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只有一个标识符,但是,如果需要不只一个标识符,其他的标识符一般被认为是这个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。按照惯例,这些名称通常是由字符数字组成,但是也可以包含一些特殊字符。如果你想向bean中引入其他别名,你可以在name属性中指定它们,不同名称之间以逗号、分号或者空格分隔。作为历史记录,在Spring3.1之前的版本中,id属性被定义为xsd:ID类型,这限制了可能的字符。在Spring3.1版本中,被定义成了xsd:string类型。需要注意,Bean的id唯一性仍然由容器强制执行,而不再由XML解析器强制执行。

 

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提供name或者id属性。如果name或者id没有被显示提供,那么容器将会为那个bean自动生成一个唯一的name。然而,如果你想通过ref元素或者服务定位器样式查找来引用bean,你必须提供一个name。不提供name的机制类似于使用 inner beans和自动注入连接 autowiring collaborators

 

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.beans.Introspector.decapitalize中定义的规则相同。

 

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的定义中,你可以通过使用id属性和name属性为Bean提供不只一个的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.

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.

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

然而,在Bean定义的地方所有的别名并不总是足够的。有时,需要为其他地方定义的Bean引入别名。在大型系统中,配置通常被分隔存放在各个子系统中,每个子系统都有它们自己的对象定义。在基于XML的配置元数据中,你可以使用<alias/>元素来实现。

在这个例子中,在一个容器中被命名为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:

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

举个例子,子系统A的配置元数据可以通过subsystemA-dataSource名称引用一个数据源。子系统B的配置元数据通过subsystemB-dataSource名称引用数据源。当一个主应用程序同时需要使用到这两个子系统,主应用程序通过名称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.

现在每个组件和主应用程序都可以通过一个唯一的且可以保证和其他定义不冲突的名称来引用相同的数据源对象。

 

1.3.2. Instantiating beans

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对应的配方,并使用这个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:

  • 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.

  • 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.

在使用基于XML的配置元数据时,你可以使用<bean/>对象中的class属性指定对象的类型。class属性,是BeanDefinition对象实例中的class属性,通常是强制要求的(对于例外情况,可以参见Instantiation using an instance factory methodBean definition inheritance)。你可以用下面两者方式中的任意一种使用class属性。

  • 通常,指定用于构造的Bean类对象,这样容器可以自动通过反射调用它的构造方法来创建bean对象,这与Java代码中使用new操作符创建对象相同。
  • 指定包含静态工厂方法的实际类,这个静态工厂方法可以被调用来创建对象。容器通过调用静态工厂方法来创建Bean对象并不常见。从静态工厂方法返回的对象类型可能是同一个类或者完全是另一个类。

 

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对象对应的类就可以了。然而,由于依赖于Spring 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容器可以管理你希望管理的所有类型,并不仅限于管理真实的JavaBeans。大多数Spring用户更倾向于使用只包含一个默认构造函数和适当的getter/setter方法的JavaBeans对象。你可以在你的容器中拥有其他非bean类型的类。例如,你需要一个完全不遵守JavaBean规范的连接池,Spring也同样可以管理它。

 

With XML-based configuration metadata you can specify your bean class as follows:

<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.

你可以使用下面的XML配置元数据指定你的bean类。

有关向构造函数提供参数以及在对象构造之后设置对象实例属性的详细信息,参见 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定义就是通过调用factory-method方法来创建一个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.

想要了解更多关于给静态工厂方法提供参数的信息,或者给工厂返回对象设置属性的信息,可以参见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,这个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是指那些在容器中配置用来通过实例工厂方法或静态工厂方创建对象的对象。相比之下,FactoryBean特指Spring中的FactoryBean对象。

 

©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:白松林 返回首页