1. 简介
Configurable在英文中的意思可配置的、结构的,美式发音为/kənˈfɪgjərəbl/
。 @Configurable注解是Spring框架提供的一个注解,主要用于使类能够接受Spring驱动的配置,可以理解为赋予这个类进行Spring驱动配置的资格,即使这些类的实例不是由Spring容器直接实例化的,如显式通过new操作符以编程方式创建或者由ORM框架为数据库查询结果而创建,在最简单的情况下,可以把其作为一个标记注解。
2. 基本信息
所属框架 | Spring Framework |
---|---|
框架版本 | 6.1.4 |
所属子项目 | spring-beans |
全路径类名 | org.springframework.beans.factory.annotation.Configurable |
起始版本 | 2.0 |
注解行数 | 63 |
3. 注解元素
- @Target(ElementType.TYPE) :指定 @Configurable注解只能应用于类、接口或枚举声明上。
- @Retention(RetentionPolicy.RUNTIME) :指定 @Configurable注解在运行时保持有效,这允许通过反射访问注解信息。
- @Inherited :表明如果一个类使用了 @Configurable注解,那么其子类也会继承该注解,使得子类同样可以享受Spring配置。
- @Documented :表明 @Configurable注解的信息会出现在JavaDoc中,增加代码的可读性和文档的完整性。
另外:接口上的注解不被继承。
4. 注解属性
- value:提供了一种指定bean定义名称的方式,用作配置模板。默认为空字符串。
- autowire :定义了依赖注入的方式。可以选择通过类型(BY_TYPE)、通过名称(BY_NAME)、不自动装配(NO)等。默认为Autowire.NO,即不进行自动装配。
- dependencyCheck :指定是否对配置对象进行依赖检查。默认为false,即不进行依赖检查。如果这个属性被设置为 true,Spring会在配置后验证所有的属性(不是基本类型或集合)是否已经被设置。
- preConstruction :指定依赖注入是否在对象构造之前进行。默认为false,即在对象构造之后进行依赖注入。
注意:对于使用new操作符实例化的对象或者正在通过反序列化的 Serializable 对象(例如,通过 readResolve()
),如果你想让依赖关系在构造函数体运行之前被注入,从而可以在构造函数体中使用,需要将preConstruction的值设置为true。
5. 使用场景
@Configurable注解通常与AspectJ结合使用,在对象创建时(即使是通过new操作符创建的对象)注入依赖,实现依赖的自动装配。这在创建由第三方库管理的对象或需要通过程序代码直接创建对象时特别有用,因为它允许这些对象参与到Spring的依赖注入流程中来。
6. 例子
假设我们有一个Employee 类,需要在创建时自动注入一个EmployeeService 服务。通过在Employee 类上使用 @Configurable 注解,并在Spring配置中适当配置AspectJ,即可实现这一需求,从而使得即使是通过new操作符创建的Employee 对象,也能自动注入EmployeeService。
7. 单元测试
- 目标 : @Configurable旨在简化领域对象的单元测试,避免硬编码查找依赖的复杂性。
- 未织入AspectJ时 :若未通过AspectJ织入, @Configurable不会影响单元测试。可通过设置mock或stub来模拟依赖关系,以正常执行测试。
- 织入AspectJ后 :即便AspectJ对 @Configurable 进行了织入,依然可以在Spring容器外部进行单元测试。但需注意,此时创建 @Configurable对象将引发警告,提示未通过Spring进行配置,尽管这不妨碍测试的进行。
这种方式确保了即使在AspectJ增强的情况下,也能灵活地对领域对象进行单元测试,同时提醒关于配置状态的信息。
8. 注意事项
- 避免双重初始化 :确保不在Spring容器已经管理的Bean上使用 @Configurable注解。这样做可能导致对象被初始化两次:一次是通过Spring容器的正常流程,另一次是通过AspectJ切面的介入。双重初始化不仅增加性能负担,还可能引起对象状态的意外改变,导致应用行为异常。
- 慎用于非Spring管理对象 : @Configurable注解的主要用途是为在运行时创建的、非Spring容器管理的对象提供依赖注入能力。只有当你确实需要此功能时,才应使用该注解。
- 性能考量 :认识到使用 @Configurable 可能对应用程序的性能有所影响。每当一个被 @Configurable注解的对象被创建时,AspectJ切面的介入可能会增加额外的处理时间。
- 排错难度 :使用 @Configurable可能使得排查问题变得更加困难,特别是在对象状态不一致或预期之外的行为发生时。由于切面的介入可能在不显眼的地方改变了对象的状态,这可能使得问题的根源不那么直观。
9. 总结
@Configurable注解提供了一种强大的机制,通过它,我们可以将Spring的依赖注入和配置功能扩展到几乎所有对象上,极大地提升了Spring应用的灵活性和可配置性。