Spring注解
注解术语
-
元注解:注解在别的注解上的注解,比如@Documented、@Retention、@Target
-
刻板注解:被元注解,用来表明特殊的角色@Controller、@Service、@Repository。Stereotype Annotation 我喜欢翻译它为刻板注解,因为一看到@Repository我就知道这个组件是DAO层的组件,这是一个刻板的印象。
-
组合注解:被多个元注解,合成多个功能,如@TransactionalService,被@Transactional和@Service两个元注解注解,被@TransactionalService注解的类可以看作添加了这两个注解。
注解存在
- 在Java8里面,直接存在、间接存在、存在是一样的意思
- 在Spring里面,如果一个类声明了@TransactionalService,可以说这个类元存在@Transactional和@Service
属性别名和覆盖
- 显式别名:一个注解里面的两个属性互相使用@AliasFor进行标注。如a1<-->a2,所以a1和a2是显式别名。
public @interface A{
@AliasFor(attribute="a2")
String a1();
@AliasFor(attribute="a1")
String a2();
}
- 隐式别名:注解里面的两个或者多个属性使用@AliasFor标注为显式的覆盖元注解上的同一属性,他们是隐式别名。他们指的是当前注解里的两个或者多个属性,跟元注解上的属性没关系。如1->a,b2->a,所以b1和b2是隐式别名。
public @interface A{
String a();
}
public @interface B{
@AliasFor(annotation = A.class,attribute="a")
String b1();
@AliasFor(annotation = A.class,attribute="a")
String b2();
}
- 传递隐式别名:一个注解里面的两个或者多个属性,都使用@AliasFor显式覆盖了元注解上的属性,而且这些属性能通过传递法则有效的覆盖相同的属性,他们是传递性隐式别名。如b1->a1,b2->a2,a1<-->a2,所以b1和b2是传递隐式别名。
public @interface A{
@AliasFor(attribute="a2")
String a1();
@AliasFor(attribute="a1")
String a2();
}
public @interface B{
@AliasFor(annotation = A.class,attribute="a1")
String b1();
@AliasFor(annotation = A.class,attribute="a2")
String b2();
}
属性覆盖
-
一个注解里面的属性覆盖了元注解里面的属性,分为三类
- 隐式覆盖:注解One的A属性隐式覆盖了Two的A属性
@Two public @interface One{ String A(); } public @interface Two{ String A(); }
- 显式覆盖:注解One的B属性显式覆盖了Two的A属性
@Two public @interface One{ @AliasFor(annotation = Two.class,attribute="A") String B(); } public @interface Two{ String A(); }
- 传递显式覆盖:注解One的A属性显式覆盖Two的B属性,Two显式覆盖Three的C属性,那么One的A属性就传递显式覆盖了Three的C属性。
@Two public @interface One{ @AliasFor(annotation = Two.class,attribute="A") String A(); } @Three public @interface Two{ @AliasFor(annotation = Three.class,attribute="C") String B(); } public @interface Three{ String C(); }
问题?
-
@AliasFor能用在@Component和@Qualifier注解的value属性上吗?
- No!原因:生不逢时。@AliasFor出现的比较晚,为了保持向下兼容,放弃了这部分的支持。
-
注解为啥这么多弯弯绕绕的东西?
- 注解不支持继承,这种方式可以有效的对注解进行扩展使用。
-
@AliasFor的原理是什么?
- 动态代理。通过Spring的AnnotatedElementUtils和AnnotationUtils获取注解信息时,得到的是一个代理对象。创建代理对象过程中会解析@AliasFor注解。