美文网首页Spring Boot程序员IT技术篇
Spring Boot 注解—基本知识

Spring Boot 注解—基本知识

作者: 玩命有人疼 | 来源:发表于2018-07-02 18:47 被阅读146次

    注:该部分内容包含注解基本知识的讲解,如果对学习过java注解的同学可以直接跳过注解讲解部分,直接查看下一小节Spring Boot 注解—常用注解即可,如果对Spring Boot或者Spring MVC也比较熟悉的同学可以跳过该节。

    注解

    我对注解的理解是,注解就是一种标记,通过这个标记我们可以获取一定的关联信息。

    为什么要学习注解

    在这里主要是现有的框架中存在大量的注解,我们需要知道主键的基本概念以及使用方法,能够更加理解这些框架,另一方面,学习注解,我们可以开发自定义注解使得代码更加简洁清晰。

    注解的分类

    1、按照声明周期

    源码注解(仅在.java文件中存在,经过编译就不存在了)
    编译时注解(在编译时起作用,即在.class文件中也仍然存在)
    运行时注解(在运行阶段起作用,有时会影响程序的运行逻辑)

    2、按照来源

    JDK自带的注解
    第三方框架注解
    自定义注解

    3、元注解(对注解进行注解的注解)

    注解的语法

    我们首先看一下@SpringBootApplication注解,这是SpringBoot HelloWorld程序中的主类的主键,我们看一下他的源码

    package org.springframework.boot.autoconfigure;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.boot.context.TypeExcludeFilter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.core.annotation.AliasFor;
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = {
            @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
        //...
    }
    

    我们通过该主键就可以帮我们自动配置好SpringBoot应用程序,通过包名我们可以看到@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan这三个注解也是属于Spring自己的注解,所以@SpringBootApplication注解是一个组合注解,去除这些组合信息,以及不必要的代码,我们再来看一下该注解:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface SpringBootApplication {
        //...
    }
    

    这就是一个注解的基本框架,首先我们知道,定义一个主键的关键字是@interface,另外我们还看到有@Target、@Retention、@Documented、@Inherited四个注解就是标注在注解上的注解即元注解,下面我们对这四个注解进行详细的讲解:
    @Target:注解的作用目标,即作用域
    可以看到它的取值是一个枚举类型,我们看一下该枚举源码:

    public enum ElementType {
        /**Class, interface (including annotation type), or enum declaration*/
        /** 类,接口   重要*/
        TYPE,
        
        /** Field declaration (includes enum constants) */
        /** 字段声明  重要*/
        FIELD,
    
        /** Method declaration */
         /** 方法声明  重要*/
        METHOD,
    
        /** Formal parameter declaration */
        /** 参数声明  重要*/
        PARAMETER,
    
        /** Constructor declaration */
        /** 构造函数声明  重要*/
        CONSTRUCTOR,
    
        /** Local variable declaration */
        /** 构局部变量声明*/
        LOCAL_VARIABLE,
    
        /** Annotation type declaration */
        /** 注解类型声明*/
        ANNOTATION_TYPE,
    
        /** Package declaration*/
        /** 包声明*/
        PACKAGE,
    
        /**
         * Type parameter declaration
         *
         * @since 1.8
         */
        TYPE_PARAMETER,
    
        /**
         * Use of a type
         *
         * @since 1.8
         */
        TYPE_USE
    }
    

    注解的作用域可以来自这些值

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Target {
        /**
         * Returns an array of the kinds of elements an annotation type
         * can be applied to.
         * @return an array of the kinds of elements an annotation type
         * can be applied to
         */
        ElementType[] value();
    }
    

    通过查看@Target的源码可以知道,其取值是一个ElementType[]数组所以,其值也可以是ElementType中的组合例如

    @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Bean {
      //...
    }
    

    Spring中的@Bean注解的作用域就是可以是在方法声明中或者注解类型声明中。
    @Retention:表示注解的声明周期,即可以是源码阶段、编译时、运行时,我们可以看一下RetentionPolicy枚举的源码

    public enum RetentionPolicy {
        /**
         * Annotations are to be discarded by the compiler. 
         * 源码阶段
         */
        SOURCE,
    
        /**
         * Annotations are to be recorded in the class file by the compiler
         * but need not be retained by the VM at run time.  This is the default
         * behavior.
         * 编译时阶段
         */
        CLASS,
    
        /**
         * Annotations are to be recorded in the class file by the compiler and
         * retained by the VM at run time, so they may be read reflectively.
         * 运行时阶段
         * @see java.lang.reflect.AnnotatedElement
         */
        RUNTIME
    }
    

    @Documented:标识在生成javadoc文档时包含该注解信息
    @Inherited:标识允许子类继承
    注解的成员:注解的成员以无参无异常的方法进行声明,可以指定默认值,成员的类型包括基本数据类型以及String、Class、Annotation、Enumeration

    注解的使用

    @<注解名>(<成员1>=<成员1值>,<成员2>=<成员2值>,...)

    注解解析

    注解解析主要是利用反射进行解析的下面我们看一个简单的例子

    package com.example.demo.annotation;
    
    import java.lang.annotation.*;
    /**
     * 描述:@Description用来对类或者方法进行注释说明的注解
     */
    @Target({ElementType.TYPE,ElementType.METHOD})//作用域:类、方法
    @Retention(RetentionPolicy.RUNTIME)//生命周期  运行时
    @Inherited//允许继承
    @Documented//生成javadoc描述符
    public @interface Description {
        String value();
    }
    
    package com.example.demo.annotation;
    
    /**
     * 描述:普通类,用来使用@Description注解
     */
    @Description("用户类")
    public class User {
    
        private String username;
    
        private String password;
    
        @Description("用户名")
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
        @Description("密码")
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    
    package com.example.demo.annotation;
    
    import java.lang.reflect.Method;
    
    /**
     * 描述:解析注解
     */
    public class ParseAnnotation {
    
        public static void main(String[] args) throws ClassNotFoundException {
            //利用反射获取类信息
            Class c=Class.forName("com.example.demo.annotation.User");
            //判断是否为@Description注解标注的类
            boolean isDescriptionAnnotationClass=c.isAnnotationPresent(Description.class);
            if(isDescriptionAnnotationClass){
                //如果是获取注解信息
                Description description= (Description) c.getAnnotation(Description.class);
                //输出
                System.out.println(description.value());
            }
            //利用反射获取所有方法信息
            Method [] ms=c.getMethods();
            for (Method m:ms){
                //判断是否为@Description注解标注的方法
                boolean isDescriptionAnnotationMethod=m.isAnnotationPresent(Description.class);
                if(isDescriptionAnnotationMethod){
                    //如果是获取注解信息
                    Description description= (Description) m.getAnnotation(Description.class);
                    //输出
                    System.out.println(description.value());
                }
            }
        }
    }
    

    运行结果:


    注解.png

    相关文章

      网友评论

        本文标题:Spring Boot 注解—基本知识

        本文链接:https://www.haomeiwen.com/subject/gtakuftx.html