类路径扫描和注册组件
本节描述了通过扫描类路径隐式检测候选组件的选项。候选组件是与过滤条件匹配的类,并在容器中注册了相应的 bean 定义。您可以使用注解(例如@Component
)、AspectJ 类型表达式或您自己的自定义过滤条件来选择哪些类具有向容器注册的 bean 定义。
从 Spring 3.0 开始,Spring JavaConfig 项目提供的许多特性都是核心 Spring Framework 的一部分。这允许您使用 Java 而不是使用传统的 XML 文件来定义 bean。查看@Configuration
、@Bean
、 @Import
和@DependsOn
注释,了解如何使用这些新功能的示例。
@Component
@Component
是任何 Spring 管理的组件的通用构造型。 @Repository
, @Service
, 和@Controller
是@Component
针对更具体用例(分别在持久层、服务层和表示层)的特化。
使用元注释和组合注释
Spring 提供的许多注解都可以在您自己的代码中用作元注解。元注释是可以应用于另一个注释的注释。
您还可以组合元注释来创建“组合注释”。例如,@RestController
Spring MVC 的注解由@Controller
和 组成@ResponseBody
。
自动检测类和注册 Bean 定义
要自动检测这些类并注册相应的 bean,您需要添加 @ComponentScan
到您的@Configuration
类中,其中basePackages
属性是两个类的公共父包。(或者,您可以指定一个逗号或分号或空格分隔的列表,其中包括每个类的父包。)
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
// ...
}
使用过滤器自定义扫描
默认情况下,使用@Component
、@Repository
、@Service
、@Controller
、 注释的类@Configuration
或本身带有注释的自定义注释是@Component
唯一检测到的候选组件。但是,您可以通过应用自定义过滤器来修改和扩展此行为。
@Configuration
@ComponentScan(basePackages = "org.example",
includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
excludeFilters = @Filter(Repository.class))
public class AppConfig {
// ...
}
在组件中定义 Bean 元数据
Spring 组件还可以将 bean 定义元数据贡献给容器。您可以使用用于在带 注释的类@Bean
中定义 bean 元数据的相同注释来执行此操作。@Configuration
以下示例显示了如何执行此操作:
@Component
public class FactoryMethodComponent {
@Bean
@Qualifier("public")
public TestBean publicInstance() {
return new TestBean("publicInstance");
}
public void doWork() {
// Component method implementation omitted
}
}
命名自动检测到的组件
当一个组件作为扫描过程的一部分被自动检测时,它的 bean 名称由该BeanNameGenerator
扫描器已知的策略生成。默认情况下,任何包含名称的Spring 原型注解 ( @Component
、@Repository
、@Service
和 ) 都会将该名称提供给相应的 bean 定义。
如果这样的注释不包含名称value
或任何其他检测到的组件(例如由自定义过滤器发现的组件),则默认 bean 名称生成器将返回未大写的非限定类名称。例如,如果检测到以下组件类,则名称为movieFinderImpl
@Service("myMovieLister")
public class SimpleMovieLister {
// ...
}
@Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
作为一般规则,只要其他组件可能显式引用它,请考虑使用注释指定名称。
为自动检测的组件提供范围
与一般 Spring 管理的组件一样,自动检测组件的默认和最常见范围是singleton
. 但是,有时您需要可以由@Scope
注释指定的不同范围。
@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}