Java注解浅谈

简介: 注解定义(来自百度百科):指示编译器如何对待您的自定义 Annotation,预设上编译器会将Annotation资讯留在class档案中,但不被虚拟机器读取,而仅用于编译器或工具程式运行时提供资讯。 随着零配置的流行,注解的使用也越来越大众化,注解的学习也很有必要。

注解定义(来自百度百科):指示编译器如何对待您的自定义 Annotation,预设上编译器会将Annotation资讯留在class档案中,但不被虚拟机器读取,而仅用于编译器或工具程式运行时提供资讯。

随着零配置的流行,注解的使用也越来越大众化,注解的学习也很有必要。最近学习了下Spring的几个注解,这里与大家分享下自己对注解的理解。
首先我们来看下@Controller这个注解的源码

?
1
2
3
4
5
6
7
8
9
10
package org.springframework.stereotype;
// 省略import以及一些注释
 
@Target ({ElementType.TYPE})
   @Retention (RetentionPolicy.RUNTIME)
   @Documented
   @Component
   public @interface Controller {
       String value() default "" ;
   }


不难看出,注解的关键字是@interface,很像一个接口,是不能够实例化的,然而我们在实际使用的时候,通常通过反射机制,得到注解接口的一个实例,进行逻辑处理,后面的样例会看到这种使用。(命名为value的注解方法有一个比较特别的用法,后面会提到。)

它的主体部分,定义了一个value()方法,实际上,它不仅是一个方法定义,也是注解的一个属性定义。我们使用注解进行标注的时候,是这样的:@Controller(value="MyController"),而在解析判断时,会通过controller.value()方法,得到这个具体的value值"MyController"。再看看value()后面跟着的default,这个default表面上的意思是默认值为某个值,实际上还有一个功效,表示value属性可以不输入。因此我们使用Controller的时候,可以直接@Controller这样使用,不需要给定value,若去掉default,不指定value,会编译失败。

再看看这个注解定义前面的注解。@Target,顾名思义,就是指定当前注解使用的作用目标。如果大家使用Eclipse等开发工具,将鼠标放到ElementType.TYPE处,会看到其注释内容,大致意思是说,这个注解要放到类、接口或者枚举类型声明的地方。也就是说,我们的@Controller注解只能放到类、接口、枚举定义前面,不能放到成员属性、方法、参数等地方。大家可以跟进ElementType,这里定义了“TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE”这么些枚举,根据注释(或者从枚举英文含义也不难猜测。这也从另一方面说明,合理的命名有助于提高代码可读性)很容易知道,注解可以实现注解到类文件的各个地方。

@Retention(RetentionPolicy.RUNTIME),Retention可能不好猜,但是看到后面的RUNTIME,精神一震,猜测应该是和“运行时”有关。再查看API帮助文档,Retention“指示注释类型的注释要保留多久”。这个保留多久,就要和RetentionPolicy(Retention的策略)配合使用了。Controller的Retention策略是运行时的,这样在代码运行时,可以通过反射获得这个注解。这中策略的好处,具体实现案例可以参考Spring的bean扫描以及AOP拦截的注解实现(Spring配置文件的component-scan base-package配置后,Spring bean工厂会逐个扫描包下所有类,根据其注解来生成相关bean。大家可以分析@Component、@Service、@Autowired等,其策略也是RUNTIME的)。

@Documented,如果需要通过javadoc工具文档化时,会判断这个注解,从而保留注释(具体没有实践过,不瞎诌了)。

@Component这个注解放在Controller上面,可以看做“Controller同样具有Component的作用”。实际上,目前的Spring扫描bean的时候,只认准了Component注解的。我们会看到,@Service、@Repository上面也有@Component注解。说道这里又不得不岔开下话题,来比照下@Service、@Controller、@Repository、@Component这几个注解的区别了。理论上讲,@Service是注解提供服务性质的bean上的,@Controller是注解MVC的C上的,@Repository是存储层bean使用的,而@Component是注解不区分服务还是控制的bean。实际上,这几类注解最终在Spring里都是以bean形式放到bean工厂里,没有什么区别对待。因此Spring扫描bean的时候,一律以@Component作为标记,@Service、@Controller、@Repository可以看做是一种功能预留:将来可能会对这三种注解的类做bean初始化时,做额外的增强型处理。

拆分了注解后,我们会发现注解也没那么神秘。接下来可以设计个属于自己的注解了:
自定义注解:

?
1
2
3
4
5
6
7
@Target (ElementType.TYPE)
   @Retention (RetentionPolicy.RUNTIME)
   public @interface MyAnnotation {
   String name() default "" ; // 名字
   Class<!--?--> procClass() default Object. class ; // 处理类的类型
   String value() default "" ; // 比较特别
   }


注解使用类:

?
1
2
3
// 标注时,name、procClass和value当做属性直接设值
@MyAnnotation (name= "Lily" ,procClass=TestAnnotation. class ,value= "abc" )
public class SomeClass{}


测试:

?
1
2
3
4
5
6
7
8
9
// 通过反射获得注解
SomeClass some = new SomeClass();
// 得到MyAnnotation的一个实例
MyAnnotation annotationClass = some.getClass().getAnnotation(MyAnnotation. class );
// 判断逻辑里,name和procClass当做方法用以调用
String annotationName = annotationClass.name();
System.out.println(annotationName);
Class<!--?--> clazz = annotationClass.procClass();
System.out.println(clazz);


上面定义的value()在使用时,如果不设置其它属性,只设置value,可以这样简写:@MyAnnotation("abc"),此时,value的值为"abc",其它取默认值。(不局限String类型。当然,MyAnnotation的其它方法需要提供default值。)

以上是一个简单的样例,大家可以修改Target,增减方法,实现自己需要的注解。

最后,欢迎大家拍砖。

目录
相关文章
|
1月前
|
Java Spring 容器
【Java】Spring如何扫描自定义的注解?
【Java】Spring如何扫描自定义的注解?
35 0
|
1月前
|
Java 数据库连接
hibernate注解实体类(Dept.java)
hibernate注解实体类(Dept.java)
13 1
|
3月前
|
缓存 安全 Java
Java学习—注解与反射2(狂神说超详细版)
Java学习—注解与反射(狂神说超详细版)
Java学习—注解与反射2(狂神说超详细版)
|
3月前
|
Java 程序员 编译器
Java学习—注解与反射1(狂神说超详细版)
Java学习—注解与反射(狂神说超详细版)
|
1月前
|
Java 数据库连接
Hibernate中使用Criteria查询及注解——(Dept.java)
Hibernate中使用Criteria查询及注解——(Dept.java)
14 1
|
28天前
|
存储 SQL Java
【Java技术指南】「JPA编程专题」让你不再对JPA技术中的“持久化型注解”感到陌生了(二)
【Java技术指南】「JPA编程专题」让你不再对JPA技术中的“持久化型注解”感到陌生了
44 1
|
2天前
|
Java 测试技术 编译器
JAVA注解
JAVA注解
9 0
|
1月前
|
Java 数据库连接
hibernate注解实体类(Emp.java)
hibernate注解实体类(Emp.java)
14 1
|
1月前
|
Java 数据库连接
Hibernate中使用Criteria查询及注解——(DeptTest.java)
Hibernate中使用Criteria查询及注解——(DeptTest.java)
8 1
|
1月前
|
Java 数据库连接
Hibernate中使用Criteria查询及注解——(Emp.java)
Hibernate中使用Criteria查询及注解——(Emp.java)
9 0