Spring Framework Documentation (5.3.10)
Core | IoC Container, Events, Resources, i18n, Validation, Data Binding, Type Conversion, SpEL, AOP. |
1. The IoC Container
1.1. Introduction to the Spring IoC Container and Beans(Spring IoC容器和bean简介)
1.2. Container Overview (容器概览)
1.4.1. Dependency Injection(依赖注入)
1.4.1.1. Constructor-based Dependency Injection(基于构造函数的依赖注入) (Part I)
1.4.1.1. Constructor-based Dependency Injection(基于构造函数的依赖注入) (Part II)
1.4.1.2.Setter-based Dependency Injection(基于Setter的依赖注入)
1.4.1.3.Dependency Resolution Process(依赖解析过程)
1.4.1.4. Examples of Dependency Injection(依赖注入示例)
1.4.2. Dependencies and Configuration in Detail(依赖与配置详细介绍)
1.4.3. Using depends-on(使用depends-on)
1.4.4. Lazy-initialized Beans(延迟初始化Bean)
1.4.5. Autowiring Collaborators(自动装配协作者)
1.4.6.1. Lookup Method Injection(查找方法注入)
1.4.6.2. Arbitrary Method Replacement(任意方法替换)
下载此文档精编完整版
No. | 内容 | 下载地址 | 文档内容目录 |
1 | 中英双语精编版 第一部分 | PDF下载 | 内容目录 |
2 | 中英双语精编版 第二部分 | PDF下载 | 内容目录 |
3 | 中文精编版 第一部分 | PDF下载 | 内容目录 |
4 | 中文精编版 第二部分 | PDF下载 | 内容目录 |
更多章节内容,请点击查看: Core Technologies
1.4.1.2.Setter-based Dependency Injection(基于Setter的依赖注入)
Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static
factory method to instantiate your bean.
基于Setter的依赖注入是由容器在调用无参数构造函数或无参数静态工厂方法(no-argument static
factory method)实例化bean之后,在bean上调用Setter方法来完成的。
The following example shows a class that can only be dependency-injected by 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注入(pure setter injection)方式进行依赖注入的类。这个类是传统的Java。它是一个POJO,不依赖于特定于容器的接口、基类或注解(interfaces, base classes, or annotations)。
Java
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...
}
Kotlin
class SimpleMovieLister {
// a late-initialized property so that the Spring container can inject a MovieFinder
lateinit var 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 (that is, programmatically) but rather with XML bean
definitions, annotated components (that is, classes annotated with @Component
, @Controller
, and so forth), 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支持基于构造函数(constructor-based)和基于setter(setter-based)的DI(依赖注入)。在通过构造函数方法注入一些依赖项之后,它还支持基于setter的DI。您可以采用BeanDefinition
的形式配置依赖项,将其与PropertyEditor
实例一起使用,以将属性从一种格式转换为另一种格式。然而,大多数Spring用户并不直接使用这些类(即编程),而是使用基于Java的@Configuration
类中的XML bean
定义、带注解的组件(即用@Component
、 @Controller
等注解的类)或@bean方法。然后,这些源(sources)在内部转换为BeanDefinition的实例,并用于加载整个Spring IoC容器实例。
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 be a required dependency; however, constructor injection with programmatic validation of arguments is preferable.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not
null
. Furthermore, constructor-injected components are always returned to the 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.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.
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.
基于构造函数还是基于setter的DI?
因为您可以混合使用基于构造函数和基于setter的DI,所以对于强制依赖项使用构造函数,对于可选依赖项使用setter方法或配置方法是一个很好的经验法则。注意,在setter方法上使用 @Required注解可以使属性成为必需的依赖项;但是,构造函数注入和参数的编程验证更可取。
Spring团队通常提倡构造函数注入,因为它允许您将应用程序组件(application component)实现为不可变对象,并确保所需的依赖项不为null。此外,构造函数注入的组件总是以完全初始化的状态返回给客户端(调用)代码。作为旁注,大量构造函数参数是一种糟糕的代码味道,这意味着类可能有太多的责任,应该进行重构以更好地完成关注点的适当分离。
Setter注入应该主要用于可选的依赖项,这些依赖项可以在类中分配合理的默认值。否则,必须在代码使用依赖项的任何地方执行非null检查(not-null check)。setter注入的一个好处是setter方法使该类的对象易于以后重新配置或重新注入。因此,通过JMX MBeans进行管理是setter注入的一个引人注目的用例。
使用对特定类最有意义的DI样式。有时,在处理您没有源代码的第三方类时,会为您做出选择。例如,如果第三方类不公开任何setter方法,那么构造函数注入可能是唯一可用的DI形式。