原文链接:Core Technologies
spring version 5.3.9
上一篇:1.2容器总览
Spring IOC容器管理一个或多个bean。这些bean是使用配置文件创建的(例如,以XML
在容器本身中,这些bean定义表示为 BeanDefinition 对象,包含以下元数据:
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.
这些数据转换为组成每个bean定义的一组属性。下表介绍了这些属性:
This metadata translates to a set of properties that make up each bean definition. The following table describes these properties:
Property 属性名 | Explained in… 解释 |
---|---|
Class |
Instantiating Beans 实例化Bean |
Name |
Naming Beans 命名Bean |
Scope |
Bean Scopes 作用域 |
Constructor arguments |
Dependency Injection 依赖注入的构造器参数 |
Properties |
Dependency Injection 依赖注入的属性值 |
Autowiring mode |
Autowiring Collaborators 自动注入的依赖(和自动注入到其他Bean) |
Lazy initialization mode |
Lazy-initialized Beans 懒加载 |
Initialization method |
Initialization Callbacks 初始化化方法 |
Destruction method |
Destruction Callbacks 销毁方法 |
除了定义容器信息,比如怎么创建指定的Bean,ApplicationContext
的实现还允许注册已创建好的对象到容器中。这可以通过授权 ApplicationContext 的 BeanFactory getBeanFactory()方法。这个方法返回的是
BeanFactory 的实现DefaultListableBeanFactory。DefaultListableBeanFactory
通过registerSingleton(..)
and registerBeanDefinition(..)
方法支持注册功能。不过,典型applications的功能是通过定义唯一的配置数据实现。
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 thegetBeanFactory()
method, which returns the BeanFactoryDefaultListableBeanFactory
implementation.DefaultListableBeanFactory
supports this registration through theregisterSingleton(..)
andregisterBeanDefinition(..)
methods. However, typical applications work solely with beans defined through regular bean definition metadata.
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 通常只有一个唯一Id。但是如果要有多个,多余的那个可以作为别名。
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.
在基于XML配置的应用中,你可以使用id 属性,name 属性,或者同时用,用于区分指定的Bean。Id属性让你用唯一的id进行区分。照理说,这些字段值是子母数字,但是他们可以包含特殊字符。如果你想让你的Bean 暴露其他的别名,你可以指定 name 属性,并用 逗号 , 分号 ; 或者空格进行分隔。Spring 3.1以后,id属性定义在了 xsd:ID 的类型了,可能是有(XML 规范层面的)字母约束的。Spring 3.1 以后 id 属性还是容器层面的保证,不通过XML 解析器。
In XML-based configuration metadata, you use the
id
attribute, thename
attribute, or both to specify the bean identifiers. Theid
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 thename
attribute, separated by a comma (,
), semicolon (;
), or white space. As a historical note, in versions prior to Spring 3.1, theid
attribute was defined as anxsd:ID
type, which constrained possible characters. As of 3.1, it is defined as anxsd:string
type. Note that beanid
uniqueness is still enforced by the container, though no longer by XML parsers.
现在,你不必非要为Bean提供name 或者id 。如果你不想定义name或者id ,容器会生成一个独一无二的name或者Id。不过如果你想通过name关联使用这个bean,比如通过ref 元素引用或者服务定位的方式查找,你必须提供一个name。不提供name往往用于使用内部的bean,自动注入式引用。
You are not required to supply a
name
or anid
for a bean. If you do not supply aname
orid
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 theref
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.
Bean命名惯例 Bean Naming Conventions
为Bean命名用Java为实例字段命名标准就行了。Bean 的名称用小写字母开始,并遵循驼峰法则就行了。比如 accountManager
, accountService
, userDao
, loginController
,等等。
遵循惯例的命名法则让你的配置更易读,更好理解。并且,如果你使用Spring AOP,使用名称引用关联会有更多便利。
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.
当在classpath 进行组件扫描的时候,Spring会为没有命名的组件生成名称,遵循的是之前描述的规则: 本质上,使用简单的类名并将其初始字符改为小写。但是,在特殊情况下,当第一个和第二个字符都是大写时,原始大小写将被保留。这些规则与java.beans.Introspector.decapitalize 定义的规则相同。 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 |
为Bean定义别名 Aliasing a Bean outside the Bean Definition
在bean定义中,通过使用id属性指定最多一个名称,用name属性定义若干个名称,这样可为bean提供多个名称。这些名称可以是在同一bean中等效,在某些情况下非常有用,例如,应用程序中的每个组件引用公共依赖项,但使用的是该组件本指定的的bean名称。
指定实际定义bean的所有别名并不总是足够的。有时需要为在别处定义的bean引入别名。在大型系统中,配置通常在每个子系统之间分割,每个子系统都有自己的对象定义集。在基于XML的配置元数据中,您可以使用
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 thename
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.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:
在上面的例子中,在同一个容器中,一个命名为fromName 的Bean,在使用者合格别名定以后,也可以用 toName 进行引用。
In this case, a bean (in the same container) named
fromName
may also, after the use of this alias definition, be referred to astoName
.
比如,配置文件中对子系统A来说可以用subsystemA-dataSource 引用一个数据源。子系统b可能用 subsystemB-dataSource 指向一个数据源。当主要程序使用这两个子系统的时候,主程序可以引用数据源 myApp-dataSource 。为了拥有所有的三个名称指向同一个对象,你可以添加下面的别名配置到配置文件中。
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 ofsubsystemB-dataSource
. When composing the main application that uses both these subsystems, the main application refers to the DataSource by the name ofmyApp-dataSource
. To have all three names refer to the same object, you can add the following alias definitions to the configuration metadata:
现在所有的组件和主程序都可以指向同一个数据源了,并且名称都是不同的,保证了相互不干扰,相当于有效的创建了一个命名空间,但是他们指向的同一个Bean。
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.
JAVA代码配置 Java-configuration
如果你使用java代码配置,@Bean注解可以被用来提供别名,可以参考
Using the @Bean Annotation 。
If you use Java configuration, the
@Bean
annotation can be used to provide aliases. See Using the @Bean Annotation for details.
一个Bean 的定义本质是重复的创建一个或多个对象。容器在被调用获取Bean时查看已命名的bean列表,并使用该bean定义封装的配置元数据创建(或获取)实际对象。
如果你使用基于XML的配置,你可以通过Class
属性是一个 BeanDefinition 的实例。有下面两种方法使用 Class
属性。
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 theelement. This
class
attribute (which, internally, is aClass
property on aBeanDefinition
instance) is usually mandatory. (For exceptions, see Instantiation by Using an Instance Factory Method and Bean Definition Inheritance.) You can use theClass
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 astatic
factory method on a class to create the bean. The object type returned from the invocation of thestatic
factory method may be the same class or another class entirely.
嵌入式类名 Nested class names
如果你想要的为内部类配置一个名字,你可以用二进制名称或者内部类的源码的名字。
比如,有一个com.example
包的SomeThing
类,这个类有一个静态的内部类叫OtherThing配置名字。
他们的名字可以用$ 或者 . 进行分隔。比如 com.example.SomeThing$OtherThing
或者 com.example.SomeThing.OtherThing。
If you want to configure a bean definition for a nested class, you may use either the binary name or the source name of the nested class.
For example, if you have a class called
SomeThing
in thecom.example
package, and thisSomeThing
class has astatic
nested class calledOtherThing
, they can be separated by a dollar sign ($
) or a dot (.
). So the value of theclass
attribute in a bean definition would becom.example.SomeThing$OtherThing
orcom.example.SomeThing.OtherThing
.
构造方法实例化 Instantiation with a Constructor
在使用构造方法创造一个bean的时候,所有的常规类被Spring使用并管理。因此,类的开发无需实现特定接口或者特定编码。只需要具体的Bean就行了。但是,对于在使用IoC具体化Bean,需要一个默认(空)构造函数。
Spring IOC容器实际上可以管理您希望它管理的任何类。它不仅限于管理真正的JavaBeans。大多数Spring用户更喜欢实际的JavaBean,它只有一个默认(无参数)构造函数,并根据容器中的属性建模适当的setter和getter。您的容器中还可以有更多异国情调的非bean样式的类。例如,如果您需要使用一个完全不符合JavaBean规范的遗留连接池,Spring也可以管理它。
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.
使用基于XML的配置元数据,您可以按如下方式指定bean类:
With XML-based configuration metadata you can specify your bean class as follows:
更多关于设置对象和实例化属性的信息可参考 Injecting Dependencies 。
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
使用静态工厂方法创建一个Bean的时候,使用class属性来指定包含静态工厂方法的类,使用 factory-method
来指定工厂方法本身的名称。你应该可以直接调用这个方法,它有可选的参数,返回一个可用的对象,就像调用构造构造方法一样。类似的Bean 定义还有一个用途是在其他代码中调用静态工厂方法。
When defining a bean that you create with a static factory method, use the
class
attribute to specify the class that contains thestatic
factory method and an attribute namedfactory-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 callstatic
factories in legacy code.
下面的Bean定义指定了这个Bean由工程方法进行创建。这一定义不会指定返回的class类型,只会明确工厂方法。下列例子中 createInstance() 方法必须是static的
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;
}
}
对于工厂方法可选参数和工厂创建对象后设置属性值的细节,可以参考:Dependencies and Configuration in Detail
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
使用实例工厂非static方法的实例化bean,和静态工厂方法创建Bean类似。要使用这种机制,class 属性为空,factory-bean 属性指定创建bean 的工厂的类(父类),
factory-method
属性还是创建Bean的工厂方法。具体如下
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 thefactory-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 thefactory-method
attribute. The following example shows how to configure such a bean:
下面是对应的工厂的定义
The following example shows the corresponding 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 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;
}
}
这个链接展示的是工厂本身也可以被设置成依赖注入 Dependencies and Configuration in Detail.
This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See Dependencies and Configuration in Detail.
factory bean 是bean ,提供了instance 方法或者static的工厂方法创建对象。
FactoryBean 是指Spring中的一个类的实现。
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 implementation class. |
Bean的运行时类型 Determining a Bean’s Runtime Type
特定bean的运行时类型很难确定。bean配置文件定义中的指定类只是一个初始类引用,可能与声明的工厂方法组合,或者是一个FactoryBean类,这可能导致不同的bean运行时类型,或者在实例级工厂方法的情况下根本不设置(这是通过指定的工厂bean名称来解决的)。此外,AOP代理可以使用基于接口的代理来包装bean实例,并有限地公开目标bean的实际类型(仅其实现的接口)。
了解特定bean的实际运行时类型的推荐方法是对指定bean名称进行BeanFactory.getType调用。这将考虑上述所有情况,并返回BeanFactory.getBean调用将为相同bean名称返回的对象类型。
The runtime type of a specific bean is non-trivial to determine. A specified class in the bean metadata definition is just an initial class reference, potentially combined with a declared factory method or being a
FactoryBean
class which may lead to a different runtime type of the bean, or not being set at all in case of an instance-level factory method (which is resolved via the specifiedfactory-bean
name instead). Additionally, AOP proxying may wrap a bean instance with an interface-based proxy with limited exposure of the target bean’s actual type (just its implemented interfaces).The recommended way to find out about the actual runtime type of a particular bean is a
BeanFactory.getType
call for the specified bean name. This takes all of the above cases into account and returns the type of object that aBeanFactory.getBean
call is going to return for the same bean name.
下一篇:1.4 依赖项
Version 5.3.9
Last updated 2021-07-14 06:36:18 UTC