Java注解(Annotation)使用案例总结

一、java注解说明和自定义

1.1官网解释

Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。

通俗理解注解像是一个标记,可以标记在类、属性、方法等,通过反射机制动态获取标记的值,然后通过自定义注解处理器,实现自己的业务逻辑。

1.2注解分类

此处列举java7的常用注解,java8以后有新的内置注解。

1.2.1内置普通注解

作用于普通类和接口的注解

注解说明
@Deprecated主要标记过去的方法和类。如果使用标记的方法,会报编译警告
@Override检查该方法是否是重写方法
@SuppressWarnings忽视编译器的编译警告
1.2.2内置元注解

作用与自定义注解(Annotation)时使用,相当于自定注解时使用的注解。

注解说明
@Documented表示自定义注解是否通过javadoc生成到文档中
@Inherited它所标注的Annotation具有继承性,标记此注解类的子类也具有父类的注解。
@Retention用来说明该注解类的生命周期。结合枚举RetentionPolicy控制生命阶段。源码(java)、字节码(class)、运行(JVM)
@Target用来声明注解的使用范围。集合ElementType属性控制使用范围是方法、类、字段等
1.2.3自定义注解
a) 注解基本语法

自定义注解语法和接口类似,通过@interface表示

// 不添加@Target。默认全部
@Target(ElementType.TYPE)
// 不添加@Retention。默认为RetentionPolicy.CLASS
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation{
    String value() default "";
}
b) 注解范围和生命周期

@Target结合ElementType控制注解的使用范围,比如只能标记方法或者只能标记类。
java8以后有新增,此处列举java7常用属性。

package java.lang.annotation;

public enum ElementType {
    
    TYPE, /**类、接口(包括批注类型)、枚举 */

    FIELD, /** 字段声明 */

    METHOD, /** 方法声明 */
	
    PARAMETER,/** 形参数声明 */

    CONSTRUCTOR, /** 构造函数声明 */

    LOCAL_VARIABLE, /** 局部变量声明 */

    ANNOTATION_TYPE, /** 注释类型声明 */

    PACKAGE,/** 包声明 */
}

@Retention结合RetentionPolicy控制注解的生命阶段

package java.lang.annotation;

public enum RetentionPolicy {
    /**
     * 源码阶段。java源码存在,经过编译器处理,编译成class后丢弃
     */
    SOURCE,
    /**
     * 字节码阶段。java源码和编译成class时存在,JVM在运行时不保留注释。这是默认行为
     */
    CLASS,
    /**
     * 运行阶段。。java源码和编译成class时存在,并且在运行时由JVM保留,因此可以反射地读取它们
     */
    RUNTIME
}

二、自定义注解使用案例

前面初步说明注解的定义,此处说明注解的使用,主要通过java反射操作。

RetentionPolicy生命周期说明
可以通过反编译工具查看注解源码编译后的对应的class文件

级别编译后运行期说明
SOURCE不存在NULL源码编译后,字节码文件中不存在注解代码
CLASS存在NULL字节码文件存在注解代码,运行期间无法通过反射无法获取对象
RUNTIME存在注解对象字节码文件存在注解代码,运行期间无法可以通过反射获取注解对象

2.1注解在运行期调用的案例

定义注解并标记生命周期和范围,通过自定义处理器解决业务问题。

案例中注解生命周期使用RetentionPolicy.RUNTIME,所以可以通过反射动态获取注解的值。

package com.cs.spring.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 模拟SpringMVC中的Controller注解
 */
// 指定在类、接口头部标记,如果其他地方编译报错
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
    /**
     * 请求模块路径
     */
    String value() ;
}
package com.cs.spring.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 模拟SpringMVC中的RequestMapping注解
 */
// 指定在方法头部标记,如果其他地方编译报错
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
    /**
     * 请求api路径
     */
    String value();
    /**
     * 请求方式
     */
    String[] method() default {};
}
package com.cs.spring;

import com.cs.spring.annotation.Controller;
import com.cs.spring.annotation.RequestMapping;

/**
 * 模拟api接口
 */
@Controller("/user")
class UserRest {

    @RequestMapping(value = "/addUser", method = {"POST", "GET"})
    public void addUser() {
        System.out.println("addUser");
    }
}


public class Test {
    public static void main(String[] args) throws NoSuchMethodException {
        Controller controller = UserRest.class.getAnnotation(Controller.class);
        System.out.println("Controller注解    value=" + controller.value());

        RequestMapping requestMapping = UserRest.class.getMethod("addUser").getAnnotation(RequestMapping.class);
        System.out.println("RequestMapping注解  value=" + requestMapping.value() + "   method=" + requestMapping.method()[0]);
    }
}

运行结果
在这里插入图片描述

2.2注解在编译器调用的案例

java6 以后提供了编译期处理注解的方式,通过继承AbstractProcessor(注解处理器)类实现。
lombok采用的就是此方式

TODO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值