• SpringAOP02 自定义注解


    1 自定义注解

      1.1 创建自定义注解

        从java5开始就可以利用 @interface 来定义自定义注解

        技巧01:注解不能直接干扰程序代码的运行(即:注解的增加和删除操作后,代码都可以正常运行)

        技巧02:@Retention 用来声明注解的保留期限

    /*
     * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     */
    
    package java.lang.annotation;
    
    /**
     * Annotation retention policy.  The constants of this enumerated type
     * describe the various policies for retaining annotations.  They are used
     * in conjunction with the {@link Retention} meta-annotation type to specify
     * how long annotations are to be retained.
     *
     * @author  Joshua Bloch
     * @since 1.5
     */
    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
    }
    RetentionPolicy.java

        技巧03:@Target 用来声明使用该注解的目标类型

    /*
     * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     */
    
    package java.lang.annotation;
    
    /**
     * The constants of this enumerated type provide a simple classification of the
     * syntactic locations where annotations may appear in a Java program. These
     * constants are used in {@link Target java.lang.annotation.Target}
     * meta-annotations to specify where it is legal to write annotations of a
     * given type.
     *
     * <p>The syntactic locations where annotations may appear are split into
     * <em>declaration contexts</em> , where annotations apply to declarations, and
     * <em>type contexts</em> , where annotations apply to types used in
     * declarations and expressions.
     *
     * <p>The constants {@link #ANNOTATION_TYPE} , {@link #CONSTRUCTOR} , {@link
     * #FIELD} , {@link #LOCAL_VARIABLE} , {@link #METHOD} , {@link #PACKAGE} ,
     * {@link #PARAMETER} , {@link #TYPE} , and {@link #TYPE_PARAMETER} correspond
     * to the declaration contexts in JLS 9.6.4.1.
     *
     * <p>For example, an annotation whose type is meta-annotated with
     * {@code @Target(ElementType.FIELD)} may only be written as a modifier for a
     * field declaration.
     *
     * <p>The constant {@link #TYPE_USE} corresponds to the 15 type contexts in JLS
     * 4.11, as well as to two declaration contexts: type declarations (including
     * annotation type declarations) and type parameter declarations.
     *
     * <p>For example, an annotation whose type is meta-annotated with
     * {@code @Target(ElementType.TYPE_USE)} may be written on the type of a field
     * (or within the type of the field, if it is a nested, parameterized, or array
     * type), and may also appear as a modifier for, say, a class declaration.
     *
     * <p>The {@code TYPE_USE} constant includes type declarations and type
     * parameter declarations as a convenience for designers of type checkers which
     * give semantics to annotation types. For example, if the annotation type
     * {@code NonNull} is meta-annotated with
     * {@code @Target(ElementType.TYPE_USE)}, then {@code @NonNull}
     * {@code class C {...}} could be treated by a type checker as indicating that
     * all variables of class {@code C} are non-null, while still allowing
     * variables of other classes to be non-null or not non-null based on whether
     * {@code @NonNull} appears at the variable's declaration.
     *
     * @author  Joshua Bloch
     * @since 1.5
     * @jls 9.6.4.1 @Target
     * @jls 4.1 The Kinds of Types and Values
     */
    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
    }
    ElementType.java

        坑01:自定义注解允许定义成员,但是这里的成员在进行声明时必须是无入参、无抛出异常的方式进行声明;而且成员只能是方法

        坑02:在给成员指定默认值是必须使用default关键字

    package cn.test.demo.base_demo.annotations;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface NeedTest {
        boolean value() default true;
    }

      1.2 使用注解

        1.2.1 创建一个SrpingBoot项目

          下载地址:点击前往

        1.2.2 新建一个自定义注解类

    package cn.test.demo.base_demo.annotations;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface NeedTest {
        boolean value() default true;
    }
    NeedTest.java

        1.2.3 新建一个服务类

          在该服务类的方法中使用刚刚创建的自定义注解

    package cn.test.demo.base_demo.service;
    
    import cn.test.demo.base_demo.annotations.NeedTest;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;
    
    /**
     * @author 王杨帅
     * @create 2018-04-29 21:31
     * @desc 学生服务类
     **/
    @Service
    @Slf4j
    public class StudentService {
    
        private final String className = getClass().getName();
    
        @NeedTest()
        public void insert() {
            log.info("===/" + className + "/insert===新增操作");
        }
    
        @NeedTest(value = false)
        public void delete() {
            log.info("===/" + className + "/delete===删除操作");
        }
    
    }
    StudentService.java

        1.2.4 访问注解

          从Java5开始包、类、构造器、方法、字段等都反射对象都开始支持访问注解信息的方法

        /**
         * {@inheritDoc}
         * @throws NullPointerException  {@inheritDoc}
         * @since 1.5
         */
        public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
            return super.getAnnotation(annotationClass);
        }
    package cn.test.demo.base_demo.service;
    
    import cn.test.demo.base_demo.annotations.NeedTest;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.lang.reflect.Method;
    
    import static org.junit.Assert.*;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    public class StudentServiceTest {
    
        private final String className = getClass().getName();
    
        @Test
        public void test01() {
            Class cla = StudentService.class;
            Method[] methods = cla.getDeclaredMethods();
            log.info("===/" + className + "/test01===方法数量为:{}", methods.length);
            for (Method method : methods) {
                NeedTest nt = method.getAnnotation(NeedTest.class);
                if (nt.value()) {
                    log.info("===" + method.getName() + "()需要测试");
                } else {
                    log.info("===" + method.getName() + "()不需要进行测试");
                }
    
            }
        }
    
        @Test
        public void insert() throws Exception {
        }
    
        @Test
        public void delete() throws Exception {
        }
    
    }
    StudentServiceTest.java

          

  • 相关阅读:
    Git 基本使用
    vue cli 构建的 webpack 项目设置多页面
    vue父子组件通信
    路由 vue-router
    IE浏览器下 Vue2.x 和 Angular 应用无法打开
    点击组件外使组件隐藏
    vue2.x 随记
    python学习之路 二 :基本数据类型
    python学习之路 一 :编程语言介绍
    .net Timer定时执行
  • 原文地址:https://www.cnblogs.com/NeverCtrl-C/p/8973014.html
Copyright © 2020-2023  润新知