1. Spring 注解驱动发展
- Spring 1.x 时代:@Transactional 和 @ManagedResource
- Spring 2.5 时代:
- 组件定义:@Component 及其派生注解 @Controller、@Service、@Repository。
- 依赖注入:@Autowired、@Qualifier、@Resource
- 生命周期:@PostConstruct、@PreDestroy
- 注解装配:@Import
- Spring 3.0 时代:
- 配置类:@Configuration
- 组件定义:@Bean、@ImportResource
- Spring 3.1 时代:
- 注解装配:@ComponentScan
- 条件装配:@Profile
- Spring 4.0 时代:
- 条件装配:@Conditional
Spring 5.0 时代:
- 注解装配:@Indexed
2. Spring 注解编程模型
Spring Annotation Programming Model[1] (【译】spring注解编程模型)官网的 wiki 中,对 Spring 注解驱动模型总结的非常全面。因为注解是没有 implements 和 extends,在面向对象编程时显得有心无力。为了简化注解的编程模型,Spring 提供了以下四种注解编程模型。
比如,Spring 中的 @Component 及其派生注解 @Service、@Controller 等。如果是面向接口编程,我们只需要处理 Component 接口就可以处理其实现类 Service 和 Controller,这是面向对象编程语言的特性 - 封装、继承、多态。同样在使用注解时,我们也希望只需要处理 @Component 注解就可以处理其派生注解。
- 注解装配:@Indexed
元注解(Meta-Annotations)
- 模式注解(Stereotype Annotations)
- 组合注解(Composed Annotations)
属性别名和覆盖(Attribute Aliases and Overrides)
2.1 元注解
元注解是一种标注在别的注解之上的注解。如果一个注解可以标注在别的注解上,那么这个注解已然是元注解。例如,任何需要被文档化的注解,都应该被
java.lang.annotation
包中的元注解@Documented
标注。@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
String value() default "";
}
2.2 模式注解
Stereotype 注解可理解为模式注解,是一种在应用中,常被用于声明要扮演某种职责或者角色的注解。Spring核心框架提供了一系列可直接使用的 stereotype 注解,包括但不限于
@Component
,@Service
,@Repository
,@Controller
,@RestController
, and@Configuration
。@Repository
,@Service
等等注解都基于@Component
的更精细化的组件注解。@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
@AliasFor(annotation = Component.class)
String value() default "";
}
说明:Spring 中只需要处理 @Component 注解就可以处理其派生注解 @Service,这样可以大大简化编程模型。
2.3 组合注解
组合注解是一种被一个或者多个元注解标注过的注解,用以撮合多个元注解的特性到新的注解。例如,@SpringBootApplication 是 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 三个注解的组合注解。另外,从技术上上讲,@SpringBootApplication 也是一个常见的 Stereotype 注解。
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
2.4 属性别名和覆盖
Attribute Alias(成员别名)将注解的一个成员名变为另一个。一个成员有多个别名时,这些别名是平等可交换的。成员别名可以分为以下几种。
1.Explicit Aliases(明确的别名):如果一个注解中的两个成员通过
@AliasFor
声明后互为别名,那么它们是明确的别名。如,@One 的 a1、a2 属性就是显式别名。- 2.Implicit Aliases(隐含别名):如果一个注解中的两个或者更多成员通过
@AliasFor
声明去覆盖同一个元注解的成员值,它们就是隐含别名。如,@One 的 a3、a4 属性就是显式别名。 - 3.Transitive Implicit Aliases(传递的隐含别名):如果一个注解中的两个或者更多成员通过
@AliasFor
声明去覆盖元注解中的不同成员,但是实际上因为覆盖的传递性导致最终覆盖的是元注解中的同一个成员,那么它们就是可传递的隐含别名。如,@One 的 a5、a6 属性就是显式别名。
Attribute Override(成员覆盖)是注解的一个成员覆盖另一个成员。成员覆盖可以分为以下几种。
- 1.Implicit Overrides(隐含的覆盖):这是一种命名规约。注解
@One
有成员A,注解@Two
有也有成员A,如果@One
本身是被元注解@Two
标注的,那么按照命名约定,注解@One
中的成员A实际会覆盖注解@Two
中的成员A(用另一种方式说,两个看似不来自不同注解的成员A指向了同一个成员A)。如,@One 的 x 属性就会隐式覆盖 @Two 中的 x 属性。 - 2.Explicit Overrides(明确的覆盖):如果元注解的成员B通过
@AliasFor
声明其别名为成员A,那么成员A就是明确的覆盖了成员B。如,@One 的 a3 属性就会隐式覆盖 @Two 中的 b3 属性。 3.Transitive Explicit Overrides(传递的明确覆盖):如果注解
@One
中的成员A明确覆盖了注解@Two
中的成员B,而且成员B实际覆盖了注解@Three
中的成员C,那么因为覆盖的传递性,所以成员A实际覆盖了成员C。如,@One 的 a5 属性就会隐式覆盖 @Three 中的 c5 属性。 ```java public @interface One { @AliasFor(value = “a2”) // 显式别名:a1、a2 String a1() default “”; @AliasFor(value = “a1”) String a2() default “”;@AliasFor(value = “b3”, annotation = Two.class) // 隐式别名:a3、a4 String a3() default “”; @AliasFor(value = “b3”, annotation = Two.class) String a4() default “”;
@AliasFor(value = “b5”, annotation = Two.class) // 可传递的隐式别名:a5、a6 String a5() default “”; @AliasFor(value = “b6”, annotation = Two.class) String a6() default “”;
String x() default “”; }
public @interface Two { @AliasFor(value = “b3”, annotation = Two.class) String b3() default “”;
@AliasFor(value = "c5", annotation = Three.class)
String b5() default "";
@AliasFor(value = "c5", annotation = Three.class)
String b6() default "";
String x() default "";
}
public @interface Three { String c5() default “”; }
<a name="HY0Bx"></a>
# 3. Spring 注解驱动设计模式
- 模块驱动:@Enable 模式
- 条件装配:
- 自动装配:
<a name="SY3Pd"></a>
## 3.1 模块驱动
@Enable 模式可以通过注解启动模块,如 EnableAspectJAutoProxy 会启动 AOP 功能。@Enable 模式往往是通过 **@Import 注解注册相应的组件**。@Import 注解可以注册 ImportSelector、ImportBeanDefinitionRegistrar、@Configuration 配置类、普通组件,具体解析详见 ConfigurationClassParser#processImports 方法。
```java
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
3.2 条件装配
条件装配是 Spring Boot 自动装配中的重要部分,详见我的另一篇文章 @Conditional
3.3 自动装配
Spring 注解原理
核心组件 - org.springframework.core.annotation.AnnotationUtils
org.springframework.core.annotation.AnnotatedElementUtils
注解查找 - org.springframework.core.annotation.AnnotationsScanner
- org.springframework.core.annotation.MergedAnnotations.SearchStrategy
- org.springframework.core.annotation.AnnotationFilter
- org.springframework.core.annotation.AnnotationsProcessor
- org.springframework.core.annotation.RepeatableContainers
注解解析(属性别名和覆盖解析) - org.springframework.core.annotation.MergedAnnotation
- org.springframework.core.annotation.AnnotationTypeMapping
注解代理
- org.springframework.core.annotation.SynthesizedMergedAnnotationInvocationHandler