前言
本系列基于最新5.3.10版本,大部分内容copy于官方文档…
官方文档地址
从Spring 3.0 开始,Spring Java Config 项目提供的许多功能都是 Spring Framework 核心的一部分。允许使用 Java 代码而不是使用传统的 XML 文件来定义 bean。比如使用@Configuration,@Bean, @Import,和@DependsOn等注解。
上一节(基于注解的容器配置) 演示了如何通过注解配置元数据注入IOC中,但是某些情况也没有完全脱离XML配置,Spring 提供了组件功能,通过标记某些类为候选组件,然后通过路径扫描过滤这些类,并最终将这些类转换为Bean对象注册到IOC中,这消除了使用 XML 执行 bean 注册的方式。
1. @Component相关注解
可以使用@Component注解标记某个类为Spring 管理的组件,同时还提供了@Repository、@Service和@Controller注解,进行的语义化的区分,实际作用和@Component一样的。
- @Repository:持久层
- @Service:服务层
- @Controller:表示层
这些注解位于spring-context模块中。
2. 元注解和组合注解
元注解:Spring 提供的许多注解都可以在自己的代码中用作元注解,元注解是可以应用于另一个注解的注解。例如,@Service注解中就添加了@Component元注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
// ...
}
组合注解:就是由多个元注解组合的注解,例如,Spring MVC中的@RestController注解是由@Controller和@ResponseBody组成的。
@Target({
ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
@AliasFor(
annotation = Controller.class
)
String value() default "";
}
还可以通过添加元注解的属性,然后扩展元注解为某种特殊条件下的注解,例如@SessionScope 注解,就是制定了属性为session的@Scope注解。
@Target({
ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope("session")
public @interface SessionScope {
@AliasFor(
annotation = Scope.class
)
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
3. 自动检测
spring可以使用@ComponentScan注解扫描包下的配置了@Compent的类并注册相应的bean。
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
// ...
}
使用XML时:
<context:component-scan base-package="org.example"/>
4. 自定义扫描使用过滤器
默认情况下,使用了@Component, @Repository, @Service, @Controller, @Configuration注解的类扫描时,都会添加到IOC中。但是,可以通过应用自定义过滤器来修改和扩展此行为。使用@ComponentScan的includeFilters或excludeFilters属性来过滤他们。
@Configuration
@ComponentScan(basePackages = "org.example",
includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
excludeFilters = @Filter(Repository.class))
public class AppConfig {
// ...
}
元素@Filter注解中type 表示过滤器类型,对应的枚举类为FilterType,支持以下选项:
过滤器类型 | 示例表达式 | 描述 |
---|---|---|
ANNOTATION (默认) | org.example.SomeAnnotation | 在目标组件中的存在的注解类型级别。 |
ASSIGNABLE_TYPE | org.example.SomeClass | 目标组件(扩展或实现)的类(或接口) |
ASPECTJ | org.example…*Service+ | 目标组件要匹配的 AspectJ 类型表达式。 |
REGEX | org.example.Default.* | 要与目标组件的类名匹配的正则表达式。 |
CUSTOM | org.example.MyTypeFilter | org.springframework.core.type.TypeFilter接口的自定义实现 |
5. 在组件中定义 Bean 元数据
Spring 组件还可以向容器提供 bean 定义元数据。
@Component
public class FactoryMethodComponent {
@Bean
@Qualifier("public")
public TestBean publicInstance() {
return new TestBean("publicInstance");
}
public void doWork() {
// Component method implementation omitted
}
}
以上代码中FactoryMethodComponent 类是一个 Spring 组件,提供了一个 bean 定义,其@Qualifier注解表示对当前Bean定义一个标识符public,还可以指定其他方法级别的注解,比如 @Scope,@Lazy和自定义限定器注解。
6. 命名自动检测组件
当一个组件被自动检测时,它的 bean 名称由该BeanNameGenerator扫描器已知的策略生成。默认情况下,任何包含名称的Spring 构造型注解(@Component、@Repository、@Service和 @Controller)其value属性值会被作为名称提供给相应的 bean 定义。
如果不包含名称value或任何其他检测到的组件(例如自定义过滤器发现的组件),则默认 bean 名称生成器返回未大写的非限定类名称。例如,如果检测到以下组件类,名称将是myMovieLister和movieFinderImpl:
@Service("myMovieLister")
public class SimpleMovieLister {
// ...
}
@Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
可以自定义 bean 命名策略。首先,实现 BeanNameGenerator 接口,并确保包含一个默认的无参数构造函数。然后,在配置扫描器时提供完全限定的类名,如以下示例注释和 bean 定义所示。
@Configuration
@ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class)
public class AppConfig {
// ...
}
如果自动检测到的组件具有相同的非限定类名而遇到命名冲突,您可能需要配置一个BeanNameGenerator默认为生成的完全限定类名的Bean名称。从 Spring Framework 5.2.3 开始, FullyQualifiedAnnotationBeanNameGenerator位于包 org.springframework.context.annotation中的可用于此类目的。
7. 为自动扫描组件定义作用域范围
与一般的Spring 管理组件一样,自动扫描的组件Bean对象的默认的范围是singleton,可以使用@Scope注解指定的不同范围。如以下示例所示:
@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
8. 带有限定符元数据的注解
当使用了自动扫描组件时,您可以@Qualifier注解实现类级别的标识符Bean。
@Component
@Qualifier("Action")
public class ActionMovieCatalog implements MovieCatalog {
// ...
}
与大多数基于注解的替代方案一样,注解元数据绑定到类定义本身,而 XML 的使用允许相同类型的多个 bean 提供其限定符元数据的变体,因为该元数据是每个- 实例而不是每个类。
9. 生成候选组件的索引
然类路径扫描非常快,但可以通过在编译时创建一个静态候选列表来提高大型应用程序的启动性能。在此模式下,所有作为组件扫描目标的模块都必须使用此机制。
首先需要引入一下包:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<version>5.3.10</version>
<optional>true</optional>
</dependency>
spring-context-indexer会生成一META-INF/spring.components文件包含在 jar 文件中。
可以看到此文件包含了该项目中定义的所有Bean。
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: