装配
创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(DI)的本质。
Spring 容器负责创建应用程序中的 bean 并通过 DI 来协调这些对象之间的关系。但是,作为开发人员,我们需要告诉 Spring 要创建哪些 bean 并且如何将其装配在一起。
Spring 提供了三种主要的装配机制:
在 XML 中进行显式配置。
在 Java 中进行显式配置。
隐式的 bean 发现机制和自动装配。
Spring 的配置风格是可以互相搭配的,所以可以选择使用 XML 装配一些 bean,使用 Spring 基于 Java 的配置(JavaConfig)来装配另一些 bean,而将剩余的 bean 让 Spring 去自动发现。
建议尽可能地使用自动配置的机制,显式配置越少越好。
当你必须要显式配置 bean 的时候(比如,有些源码不是由你来维护的,而你需要为这些代码配置 bean),推荐使用类型安全并且比 XML 更加强大的 JavaConfig。
只有当你想要使用便利的 XML 命名空间,并且在 JavaConfig 中没有同样的实现时,才应该使用 XML。
自动装配
Spring 从两个角度来实现自动化装配:
组件扫描(component scanning):Spring 会自动发现应用上下文中所创建的 bean。
自动装配(autowiring):Spring 自动满足 bean 之间的依赖。
相关的 3 个主要注解为:
在 Java 中进行显式配置
创建 JavaConfig 类的关键在于为其添加 @Configuration 注解,@Configuration 注解表明这个类是一个配置类,该类应该包含在 Spring 应用上下文中如何创建 bean 的细节。
1. 声明 bean
要在 JavaConfig 中声明 bean,我们需要编写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加 @Bean 注解。@Bean 注解会告诉 Spring 这个方法将会返回一个对象,该对象要注册为 Spring 应用上下文中的 bean。方法体中包含了最终产生 bean 实例的逻辑。
默认情况下,bean 的 ID 与带有 @Bean 注解的方法名是一样的。如果你想为其设置成一个不同的名字的话,那么可以重命名该方法,也可以通过 name 属性指定一个不同的名字。
2. 注入
在 JavaConfig 中装配 bean 的最简单方式就是引用创建 bean 的方法。
默认情况下,Spring 中的 bean 都是单例的,我们没有必要为第二个 CDPlayer bean 创建完全相同的 SgtPeppers 实例。所以,Spring 会拦截对 sgtPeppers() 的调用并确保返回的是 Spring 所创建的 bean,也就是 Spring 本身在调用 sgtPeppers() 时所创建的 CompactDisc bean。因此,在上面的程序片段中,两个 CDPlayer bean 会得到相同的 SgtPeppers 实例。
还有一种理解起来更为简单的方式:
在这里,cdPlayer() 方法请求一个 CompactDisc 作为参数。当 Spring 调用 cdPlayer() 创建 CDPlayer bean 的时候,它会自动装配一个 CompactDisc 到配置方法之中。然后,方法体就可以按照合适的方式来使用它。借助这种技术,cdPlayer() 方法也能够将 CompactDisc 注入到 CDPlayer 的构造器中,而且不用明确引用 CompactDisc 的 @Bean 方法。
通过这种方式引用其他的 bean 通常是最佳的选择,因为它不会要求将 CompactDisc 声明到同一个配置类之中。在这里甚至没有要求 CompactDisc 必须要在 JavaConfig 中声明,实际上它可以通过组件扫描功能自动发现或者通过 XML 来进行配置。你可以将配置分散到多个配置类、XML 文件以及自动扫描和装配 bean 之中,只要功能完整健全即可。不管 CompactDisc 是采用什么方式创建出来的,Spring 都会将其传入到配置方法中,并用来创建 CDPlayer bean。
混合配置
关于混合配置,第一件需要了解的事情就是在自动装配时,它并不在意要装配的 bean 来自哪里。自动装配的时候会考虑到 Spring 容器中所有的 bean,不管它是在 JavaConfig 或 XML 中声明的还是通过组件扫描获取到的。
Last updated