程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

Java注解二:实现自定义注解

发布于2021-03-13 14:08     阅读(1409)     评论(0)     点赞(10)     收藏(3)


参考:

https://blog.csdn.net/zt15732625878/article/details/100061528

http://www.shixinke.com/java/java-annotation-usage

前言
     

    上一篇文章介绍了注解的一些基本知识,这次来介绍下如何实现自定义注解及注解如何使用。

正文


     注解是一种能被添加到java源代码中的元数据,方法、类、参数和包都可以用注解来修饰。注解可以看作是一种特殊的标记,可以用在方法、类、参数和包上,程序在编译或者运行时可以检测到这些标记而进行一些特殊的处理。

注解的基本元素
     声明一个注解要用到的东西

  • 修饰符

  访问修饰符必须为public,不写默认为pubic;

  • 关键字

  关键字为@interface;

  • 注解名称

  注解名称为自定义注解的名称,使用时还会用到;

  • 注解类型元素

  注解类型元素是注解中内容,可以理解成自定义接口的实现部分;
 

  1. public @interface Info {
  2. String value() default "tracy";
  3. boolean isDelete();
  4. }

 

使用元注解修饰注解


     JDK中有一些元注解,主要有@Target,@Retention,@Document,@Inherited用来修饰注解。
@Target
  表明该注解可以应用的java元素类型

@Retention
  表明该注解的生命周期


@Document
  表明该注解标记的元素可以被Javadoc 或类似的工具文档化
@Inherited
  表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解
 

使用自定义注解

注:注解只是一种标记,如果不解析,它是不会实现任何功能的

(1)定义注解:定义标记

定义标记需要使用元注解

  1. package main.java.com.shixinke.java.demo.annotation;
  2. import java.lang.annotation.*;
  3. @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
  4. @Retention(RetentionPolicy.RUNTIME)
  5. @Inherited
  6. @Documented
  7. public @interface Check {
  8. boolean value() default false;
  9. }

注:自定义注解本质上是继承自Annotation的类

 

(2)标记注解:打标,表明此处要使用此标记

定义一个User类,标记为@Check

  1. package main.java.com.shixinke.java.demo.annotation;
  2. @Check(true)
  3. public class User {
  4. }

定义一个Person类,不标记

  1. package main.java.com.shixinke.java.demo.annotation;
  2. public class Person {
  3. }

 

(3)解析注解:扫描标记,实现功能

一般通过反射来实现扫描注解,并在解析器中实现功能:

那么注解我们写好了,具体怎么用呢?

         1. isAnnotationPresent(annotation.class):判断该程序元素上是否包含指定类型的注解

         2. getAnnotations():返回该程序元素上存在的所有注解。

         3. getDeclaredAnnotations():返回直接存在于此元素上的所有注释。 

 

  • 注解解析器来解析注解并实现功能
  1. package main.java.com.shixinke.java.demo.annotation;
  2. import java.lang.annotation.Annotation;
  3. public class CheckParser {
  4. public void parse(Class cls) {
  5. //判断注解是否生效
  6. if (cls.isAnnotationPresent(Check.class)) {
  7. //获取Check的注解对象
  8. Annotation annotation = cls.getAnnotation(Check.class);
  9. Check check = (Check) annotation;
  10. System.out.println(cls.getName() + "在检查中........");
  11. }
  12. }
  13. }
  • 调用注解解析器
  1. package main.java.com.shixinke.java.demo.annotation;
  2. public class AnnotationDemo {
  3. public static void main(String[] args) {
  4. User user = new User();
  5. Person person = new Person();
  6. CheckParser parser = new CheckParser();
  7. parser.parse(user.getClass());
  8. parser.parse(person.getClass());
  9. }
  10. }

 

运行结果:

//main.java.com.shixinke.java.demo.annotation.User在检查中........


    对于一个类或者接口来说,Class类(java.lang包下)中提供了一些方法用于反射注解,当然对于字段、方法来说反射注解的方式很类似。

  1. //返回指定的注解
  2. getAnnotation
  3. //判断当前元素是否被指定注解修饰
  4. isAnnotationPresent
  5. //返回所有的注解
  6. getAnnotations

 

可以再看一个demo:

 

  1. package com.fruit;
  2. import java.lang.annotation.*;
  3. /**
  4. * 水果名称注解
  5. * @author peida
  6. *
  7. */
  8. @Target(ElementType.FIELD)
  9. @Retention(RetentionPolicy.RUNTIME)
  10. @Documented
  11. public @interface FruitName {
  12. String value() default "";
  13. }

 

  1. package com.fruit;
  2. import java.lang.annotation.*;
  3. /**
  4. * 水果颜色注解
  5. * @author peida
  6. *
  7. */
  8. @Target(ElementType.FIELD)
  9. @Retention(RetentionPolicy.RUNTIME)
  10. @Documented
  11. public @interface FruitColor {
  12. /**
  13. * 颜色枚举
  14. * @author peida
  15. *
  16. */
  17. public enum Color{ BULE,RED,GREEN};
  18. /**
  19. * 颜色属性
  20. * @return
  21. */
  22. Color fruitColor() default Color.GREEN;
  23. }

 

  1. package com.fruit;
  2. import java.lang.annotation.*;
  3. /**
  4. * 水果供应者注解
  5. * @author peida
  6. *
  7. */
  8. @Target(ElementType.FIELD)
  9. @Retention(RetentionPolicy.RUNTIME)
  10. @Documented
  11. public @interface FruitProvider {
  12. /**
  13. * 供应商编号
  14. * @return
  15. */
  16. public int id() default -1;
  17. /**
  18. * 供应商名称
  19. * @return
  20. */
  21. public String name() default "";
  22. /**
  23. * 供应商地址
  24. * @return
  25. */
  26. public String address() default "";
  27. }

 

  1. package com.fruit;
  2. /***********注解使用***************/
  3. public class Apple {
  4. @FruitName("Apple")
  5. private String appleName;
  6. @FruitColor(fruitColor= FruitColor.Color.RED)
  7. private String appleColor;
  8. @FruitProvider(id=1,name="陕西红富士集团",address="陕西省西安市延安路89号红富士大厦")
  9. private String appleProvider;
  10. public void setAppleColor(String appleColor) {
  11. this.appleColor = appleColor;
  12. }
  13. public String getAppleColor() {
  14. return appleColor;
  15. }
  16. public void setAppleName(String appleName) {
  17. this.appleName = appleName;
  18. }
  19. public String getAppleName() {
  20. return appleName;
  21. }
  22. public void setAppleProvider(String appleProvider) {
  23. this.appleProvider = appleProvider;
  24. }
  25. public String getAppleProvider() {
  26. return appleProvider;
  27. }
  28. public void displayName(){
  29. System.out.println("水果的名字是:苹果");
  30. }
  31. }

 

  1. package com.fruit;
  2. /***********注解使用***************/
  3. public class Apple {
  4. @FruitName("Apple")
  5. private String appleName;
  6. @FruitColor(fruitColor= FruitColor.Color.RED)
  7. private String appleColor;
  8. @FruitProvider(id=1,name="陕西红富士集团",address="陕西省西安市延安路89号红富士大厦")
  9. private String appleProvider;
  10. public void setAppleColor(String appleColor) {
  11. this.appleColor = appleColor;
  12. }
  13. public String getAppleColor() {
  14. return appleColor;
  15. }
  16. public void setAppleName(String appleName) {
  17. this.appleName = appleName;
  18. }
  19. public String getAppleName() {
  20. return appleName;
  21. }
  22. public void setAppleProvider(String appleProvider) {
  23. this.appleProvider = appleProvider;
  24. }
  25. public String getAppleProvider() {
  26. return appleProvider;
  27. }
  28. public void displayName(){
  29. System.out.println("水果的名字是:苹果");
  30. }
  31. }

console:

 

 

 

另一个demo:

  1. package com.company;
  2. import java.lang.annotation.*;
  3. @Target({ElementType.FIELD, ElementType.TYPE})
  4. @Retention(RetentionPolicy.RUNTIME)
  5. @Documented
  6. public @interface Info {
  7. String value() default "Info的String";
  8. boolean isDelete();
  9. }

 

  1. package com.company;
  2. import lombok.Builder;
  3. import lombok.Data;
  4. @Data
  5. @Builder
  6. // 为Person类配置了刚刚定义的注解@Info
  7. @Info(isDelete = true)
  8. public class Person {
  9. //姓名
  10. private String name;
  11. //年龄
  12. private int age;
  13. //是否有效
  14. private boolean isDelete;
  15. }

 

  1. package com.company;
  2. public class AnnotationTest {
  3. public static void main(String[] args) {
  4. try {
  5. //获取Person的Class对象,这里是使用lombok的@builder注解
  6. Person person = Person.builder().build();
  7. Class clazz = person.getClass();
  8. //判断person对象上是否有Info注解
  9. if (clazz.isAnnotationPresent(Info.class)) {
  10. System.out.println("Person类上配置了Info注解!");
  11. //获取该对象上Info类型的注解
  12. Info infoAnno = (Info) clazz.getAnnotation(Info.class);
  13. System.out.println("person.name :" + infoAnno.value() + ",person.isDelete:" + infoAnno.isDelete());
  14. } else {
  15. System.out.println("Person类上没有配置Info注解!");
  16. }
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }

 

console:

总结:写完注解以后调用注解解析器,即判断注解是否生效以及调用注解的参数

         1. isAnnotationPresent(annotation.class):判断该程序元素上是否包含指定类型的注解。

         2. getAnnotations():返回该程序元素上存在的所有注解。

         3. getDeclaredAnnotations():返回直接存在于此元素上的所有注释。(根据是否需要)



所属网站分类: 技术文章 > 博客

作者:咿呀咿呀哟

链接:http://www.javaheidong.com/blog/article/114330/70a2e993ddf0b1545410/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

10 0
收藏该文
已收藏

评论内容:(最多支持255个字符)