zoukankan      html  css  js  c++  java
  • Java注解浅谈

    注解定义(来自百度百科):指示编译器如何对待您的自定义 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,增减方法,实现自己需要的注解。

    最后,欢迎大家拍砖。

  • 相关阅读:
    xavier NX编译caffe错误记录(二)
    ubuntu16安装微信
    linux中安装onenote(P3X OneNote)
    ubuntu16中,google浏览器安装OneNote Web Clipper插件
    酒店门锁接口说明
    在xaf 14 中实现 Tonyyang原文中的action权限
    MRP生产计划模式在多品种小批量生产过程中遭遇挑战
    C#代码
    简陋的会计凭证金额输入控件(加强) [转]
    简陋的会计凭证金额输入控件(再加强) [转]
  • 原文地址:https://www.cnblogs.com/u0mo5/p/4138682.html
Copyright © 2011-2022 走看看