jadestoner

导航

 

原文:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-definition

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 definitions).
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 size limit of the pool or the number of connections to use in a bean that manages a connection pool.

spring ioc 容器管理者一个或者多个的beans。
这些bean都是用你提供给容器的配置元数据来创建的(比如,xml形式下的定义)。
在容器里,这些bean的定义用BeanDefinition对象来表示,BeanDefinition对象包含了以下的元数据:

  • 一个包限定类名:通常是bean定义的实际实现类;
  • 控制bean行为的配置元素,通过它可以表明bean在容器是如何行为的(作用域,生命周期回调等);
  • 指向其他bean的引用,需要通过他们来完成自己的工作。这些引用也被叫做合作者或者依赖;
  • 其他的配置需要设置在新创建的对象中的(成员变量的意思)-----比如连接池的大小或者管理连接池的bean中所使用的连接数。

This metadata translates to a set of properties that make up each bean definition.
The following table describes these properties:

元数据变成一组组成每个bean定义的属性。如下表所述:

Table 1. The bean definition

属性 详情参阅
Class
Name
Scope
Constructor arguments
Properties
Autowiring mode
Lazy initialization mode
Initialization method
Destruction method

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 through the getBeanFactory() method, which returns the BeanFactory DefaultListableBeanFactory implementation.
DefaultListableBeanFactory supports this registration through the registerSingleton(..) and registerBeanDefinition(..) methods.
However, typical applications work solely with beans defined through regular bean definition metadata.

除了bean的定义(包含了如何创建一个特殊bean的信息),ApplicationContext实现类还允许在容器外创建的对象的注册。
通过ApplicationContext的【getBeanFactory】方法返回的BeanFactory就可以做到,返回的是BeanFactory的子类DefaultListableBeanFactory实现类。
DefaultListableBeanFactory类通过方法【registerSingleton】和【registerBeanDefinition】来支持注册操作。
但是,通常情况下应用只使用通过常规bean定义元数据定义的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 existing metadata and existing singleton instances is supported to some degree, the registration of new beans at runtime (concurrently with live access to the factory) is not officially supported and may lead to concurrent access exceptions, inconsistent state in the bean container, or both.

需要尽早的注册*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. However, if it requires more than one, the extra ones can be considered aliases.

每个bean都有一个或多个标识符。
这些标识符在容器中必须是独一无二的。
一个bean通常只有一个标识符,假如需要多个,多出来的可以被认为是别名。

In XML-based configuration metadata, you use the id attribute, the name attribute, or both to specify the bean identifiers.
The id attribute lets you specify exactly one id.
Conventionally, these names are alphanumeric ('myBean', 'someService', etc.), but they can contain special characters as well.
If you want to introduce other aliases for 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', 'someService'等等),当然也可以包含特殊字符。
加入你想要为一个bean引入其他的别名,你可以在元素【name】中指定他们,用逗号【,】,分号【;】或者空白符来分别他们。
历史上,spring 3.1之前的版本,元素【id】被定义成 xsd:ID 类型,限制了可能的字符;从3.1版本开始,它就被定义成了xsd:string类型。尽管不再由XML解析器保证其一致性,容器仍然强制保持其一致性。

You are not required to supply a name or an id for a bean.
If you do not supply a name or id 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 a Service Locator style lookup, you must provide a name.
Motivations for not supplying a name are related to using inner beans and autowiring collaborators.

name和id不是必须的,如果没有明确指定,容器会自动生成一个独一的name。
但是如果你想要通过名字来引用一个bean(通过使用【ref】元素或者Service Locator 寻找),你就必须为它提供一个名字。
不提供name的动机与他们相近:1.4.2的inner beans和1.4.5的 autowiring collaborators。

Bean Naming Conventions

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 there. Examples of such names include accountManager, accountService, userDao, loginController, and so forth.

Naming beans consistently makes your configuration easier to read and understand. Also, if you use Spring AOP, it helps a lot when applying advice to a set of beans related by name.

bean命名约定

  • 这个约定是当命名bean时,使用标准的java命名字段名的约定。就是驼峰命名规则。
  • 一致的命名可以让配置文件易于阅读和理解。如果你在使用spring AOP,在你将通过name将advice运用到一系列的的bean时就帮到你。

With component scanning in the classpath, Spring generates bean names for unnamed components, following the rules described earlier: 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 uses here).

当在类路径下组件扫描时,Spring自动生成bean的name,遵循着先前描述的规则:本质上就是取类名(不含包),类名的第一个单词小写。
但是特殊情况下,当类名的前几个单词都是大写时,前面介绍的规则就不适用了。同样的规则定义在java.beans.Introspector.decapitalize。

Aliasing a Bean outside the Bean Definition Bean Definition之外别名一个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 letting each component in an application refer to a common dependency by using a bean name that is specific to that component itself.

在一个bean 定义中,你可以为bean提供不止一个的名字,通过使用这样的组合即可实现:属性【id】指定的最多一个名字和属性【name】中的任意数量的其他的名字。
这些name对于同一个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, with each subsystem having its own set of object definitions.
In XML-based configuration metadata, you can use the element to accomplish this. The following example shows how to do so:

然而,在bean定义的地方就指定所有的别名并不是足够的。(意思是有的场景不满足)
有时需要为在别处定义的bean起一个别名。这种场景在大的系统中比较常见,大系统的配置会被分割在每个子系统中,而每次子系统都有自己的一套对象定义。
在基于xml配置元数据中,你可以使用元素【 】来解决这个需求。下面的例子展示了how to do。

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

In this case, a bean (in the same container) named fromName may also, after the use of this alias definition, be referred to as toName.

在这个例子中,同一个容器中一个叫fromName的bean,在使用了alias的定义后,还可以同时作为toName被引用。

For example, the configuration metadata for subsystem A may refer to a DataSource by the name of subsystemA-dataSource. The configuration metadata for subsystem B may refer to a DataSource by the name of subsystemB-dataSource.
When composing the main application that uses both these subsystems, the main application refers to the DataSource by the name of myApp-dataSource.
To have all three names refer to the same object, you can add the following alias definitions to the configuration metadata:

例如,子系统A的配置元数据可能会以名字“subsystemA-dataSource”来引用一个DataSource 对象,而子系统B则可能会以名字“subsystemB-dataSource”来引用同样的DataSource 对象。
当组成主应用时,主应用又以名字“myApp-dataSource”来引用这个DataSource 对象。
要让这三个名字都指向同一个对象,你就需要在配置元数据中加入以下的别名定义。

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-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.

现在,每个组件和主应用就可以通过独立的名字来指向同一个dataSource,并且不会与其他定义冲突。

Java-configuration
If you use Javaconfiguration, the @Bean annotation can be used to provide aliases. See Using the @Bean Annotation for details.

1.3.2. Instantiating Beans bean初始化

A bean definition is essentially 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.

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 element. This class attribute (which, internally, is a Class property on a BeanDefinition instance) is usually mandatory. (For exceptions, see Instantiation by Using an Instance Factory Method and Bean Definition Inheritance.) You can 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 with the new operator.

To specify the actual class containing the static factory method that is 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.

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.

For example, if you have a class called SomeThing in the com.example package, and this SomeThing class has a static nested class called OtherThing, the value of the class attribute on a bean definition would be com.example.SomeThing$OtherThing.

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.

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.

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

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, use the class attribute to specify the class that contains 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.

The following bean definition specifies that the bean 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. The following example shows how to specify a factory method:


The following example shows a class that would work with the preceding bean definition:

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 by 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 or 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. The following example shows how to configure such a bean:


The following example shows the corresponding Java class:

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 the following example shows:


The following example shows the corresponding Java class:

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.

In Spring documentation, “factory bean” refers to a bean that is configured in the Spring container and that creates objects through an instance or static factory method. By contrast, FactoryBean (notice the capitalization) refers to a Spring-specific FactoryBean.

posted on 2019-06-05 13:38  jadestoner  阅读(384)  评论(0编辑  收藏  举报