SpringMvc决战-【SpringMVC之自定义注解】

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

一、前言

1.1.什么是注解

1.2.注解的用处

1.3.注解的原理

二.注解父类

1.注解包括那些

2.JDK基本注解

3. JDK元注解

4.自定义注解

  5.如何使用自定义注解包括注解标记【没有任何东西】元数据注解

三.实例展示

1.案例一获取类与方法上的注解值

1.1导入一个类用于创造实例

1.2导入三个注解

1.3导入测试类

1.4测试结果】

1.测试list方法

2.测试ledit方法 

2.案例二获取类属性上的注解属性值  

2.1导入方法的类

2.导入测试类

3.测试

3.1test测试结果

3.2test4测试结果 

 3. 案例三获取参数修饰注解对应的属性值  

 1.导入方法类

2.导入测试类

3.测试结果

三. Aop自定义注解的应用

1.导入pom.xml中的依赖

2.导入自定义注解

3.编写切面类()

4.编写web类用于测试

5.打印输出的结果web类 

​编辑​


前言

讲述的为JSON返回&异常处理机制json返回就不用多说毕竟大部分数据都是通过Json来传递数据的异常返回的作用小编也就不多说了反正很重要

前台小编带来的是Spring MVC中我们可以通过自定义注解来增强和定制化我们的控制器和请求处理逻辑。自定义注解可以通过反射机制在运行时扫描并提取相关信息从而实现特定的功能和行为。

一、前言

1.1.什么是注解

Annontation是Java5开始引入的新特征中文名称叫注解。它提供了一种安全的类似注释的机制用来将任何的信息或元数据metadata与程序元素类、方法、成员变量等进行关联。为程序的元素类、方法、成员变量加上更直观、更明了的说明这些说明信息是与程序的业务逻辑无关并且供指定的工具或框架使用。Annontation像一种修饰符一样应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。

Java注解是附加在代码中的一些元信息用于一些工具在编译、运行时进行解析和使用起到说明、配置的功能。注解不会也不能影响代码的实际逻辑仅仅起到辅助性的作用。

1.2.注解的用处

 生成文档。这是最常见的也是java 最早提供的注解。常用的有@param @return 等
跟踪代码依赖性实现替代配置文件功能。比如Dagger 2 依赖注入未来java 开发将大量注解配置具有很大用处;
在编译时进行格式检查。如@override 放在方法前如果你这个方法并不是覆盖了超类方法则编译时就能检查出。

1.3.注解的原理

注解本质是一个继承了Annotation 的特殊接口其具体实现类是Java 运行时生成的动态代理类。而我们通过反射获取注解时返回的是Java 运行时生成的动态代理对象$Proxy1。通过代理对象调用自定义注解接口的方法会最终调用AnnotationInvocationHandler 的invoke 方法。该方法会从memberValues 这个Map 中索引出对应的值。而memberValues 的来源是Java 常量池
 

二.注解父类

1.注解包括那些

JDK基本注解 JDK元注解 自定义注解

2.JDK基本注解

比如@Override 重写 ​ @SuppressWarnings(value = "unchecked") 压制编辑器警告

3. JDK元注解

例子

@Retention定义注解的保留策略 @Retention(RetentionPolicy.SOURCE)             //注解仅存在于源码中在class字节码文件中不包含 @Retention(RetentionPolicy.CLASS)             //默认的保留策略注解会在class字节码文件中存在但运行时无法获得 @Retention(RetentionPolicy.RUNTIME)           //注解会在class字节码文件中存在在运行时可以通过反射获取到 ​ @Target指定被修饰的Annotation可以放置的位置(被修饰的目标) @Target(ElementType.TYPE)                     //接口、类 @Target(ElementType.FIELD)                     //属性 @Target(ElementType.METHOD)                   //方法 @Target(ElementType.PARAMETER)                 //方法参数 @Target(ElementType.CONSTRUCTOR)               //构造函数 @Target(ElementType.LOCAL_VARIABLE)           //局部变量 @Target(ElementType.ANNOTATION_TYPE)           //注解 @Target(ElementType.PACKAGE)                   //包 注可以指定多个位置例如 @Target({ElementType.METHOD, ElementType.TYPE})也就是此注解可以在方法和类上面使用 ​ @Inherited指定被修饰的Annotation将具有继承性 ​ @Documented指定被修饰的该Annotation可以被javadoc工具提取成文档.

4.自定义注解

注解分类根据Annotation是否包含成员变量,可以把Annotation分为两类: ​ 标记Annotation: 没有成员变量的Annotation; 这种Annotation仅利用自身的存在与否来提供信息 ​ 元数据Annotation: 包含成员变量的Annotation; 它们可以接受(和提供)更多的元数据;

  5.如何使用自定义注解包括注解标记【没有任何东西】元数据注解

使用@interface关键字, 其定义过程与定义接口非常类似, 需要注意的是:
   Annotation的成员变量在Annotation定义中是以无参的方法形式来声明的, 其方法名和返回值类型定义了该成员变量的名字和类型,
   而且我们还可以使用default关键字为这个成员变量设定默认值

三.实例展示

1.案例一获取类与方法上的注解值

1.1导入一个类用于创造实例

package com.lz.annotation;

public enum  TranscationModel {
    Read, Write, ReadWrite
}

1.2导入三个注解

package com.lz.annotation;

import java.lang.annotation.*;

/**
 * MyAnnotation1注解可以用在类、接口、属性、方法上
 * 注解运行期也保留
 * 不可继承
 */
@Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1 {
    String name();
}
package com.lz.annotation;

import java.lang.annotation.*;

/**
 *  MyAnnotation2注解可以用在方法上
 *  注解运行期也保留
 *  不可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
    TranscationModel model() default TranscationModel.ReadWrite;
}
package com.lz.annotation;

import java.lang.annotation.*;

/**
 * lz
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited可以被继承

@Documented
public @interface MyAnnotation3 {
    TranscationModel[] models() default TranscationModel.ReadWrite;
}

1.3导入测试类

package com.lz.annotation;

/**
 * @author lz
 * @create 2023-09-14 19:04
 */

@MyAnnotation1(name = "abc")
public class Demo1 {

    @MyAnnotation1(name = "xyz")
    private Integer age;

    @MyAnnotation2(model = TranscationModel.Read)
    public void list() {
        System.out.println("list");
    }

    @MyAnnotation3(models = {TranscationModel.Read, TranscationModel.Write})
    public void edit() {
        System.out.println("edit");
    }
}
package com.lz.annotation;

import org.junit.Test;

/**
 * @author LZ
 * @site www.javaxl.com
 */
public class Demo1Test {
    @Test
    public void list() throws Exception {
//        获取类上的注解
        MyAnnotation1 annotation1 = Demo1.class.getAnnotation(MyAnnotation1.class);
        System.out.println(annotation1.name());//abc

//        获取方法上的注解
        MyAnnotation2 myAnnotation2 = Demo1.class.getMethod("list").getAnnotation(MyAnnotation2.class);
        System.out.println(myAnnotation2.model());//Read

//        获取属性上的注解
        MyAnnotation1 myAnnotation1 = Demo1.class.getDeclaredField("age").getAnnotation(MyAnnotation1.class);
        System.out.println(myAnnotation1.name());// xyz
    }

    @Test
    public void edit() throws Exception {
        MyAnnotation3 myAnnotation3 = Demo1.class.getMethod("edit").getAnnotation(MyAnnotation3.class);
        for (TranscationModel model : myAnnotation3.models()) {
            System.out.println(model);//Read,Write
        }
    }
}

1.4测试结果】

1.测试list方法

2.测试ledit方法 

2.案例二获取类属性上的注解属性值  

2.1导入方法的类

package com.lz.annotation.demo2;

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

/**
 * @author 小李飞刀
 * @site www.javaxl.com
 */
//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
    String value() default "默认value值";

    String what() default "这里是默认的what属性对应的值";
}

2.导入测试类

package com.lz.annotation.demo2;

/**
 * @author  lz
 *
 * 获取类属性上的注解属性值
 */
public class Demo2 {
    @TestAnnotation(value = "这就是value对应的值_msg1", what = "这就是what对应的值_msg1")
    private static String msg1;

    @TestAnnotation("这就是value对应的值1")
    private static String msg2;

    @TestAnnotation(value = "这就是value对应的值2")
    private static String msg3;

    @TestAnnotation(what = "这就是what对应的值")
    private static String msg4;
}
package com.lz.annotation.demo2;

import org.junit.Test;

/**
 * @author lz
 *
 */
public class Demo2Test {
    @Test
    public void test1() throws Exception {
        TestAnnotation msg1 = Demo2.class.getDeclaredField("msg1").getAnnotation(TestAnnotation.class);
        System.out.println(msg1.value());
        System.out.println(msg1.what());
    }

    @Test
    public void test2() throws Exception{
        TestAnnotation msg2 = Demo2.class.getDeclaredField("msg2").getAnnotation(TestAnnotation.class);
        System.out.println(msg2.value());
        System.out.println(msg2.what());
    }

    @Test
    public void test3() throws Exception{
        TestAnnotation msg3 = Demo2.class.getDeclaredField("msg3").getAnnotation(TestAnnotation.class);
        System.out.println(msg3.value());
        System.out.println(msg3.what());
    }

    @Test
    public void test4() throws Exception{
        TestAnnotation msg4 = Demo2.class.getDeclaredField("msg4").getAnnotation(TestAnnotation.class);
        System.out.println(msg4.value());
        System.out.println(msg4.what());
    }
}

3.测试

3.1test测试结果

3.2test4测试结果 

 3. 案例三获取参数修饰注解对应的属性值  

通过模拟requestparam来进行操作默认情况传递为空。不会调用方法不为空不调用方法 

 1.导入方法类

package com.lz.annotation.demo3;

import java.lang.annotation.*;

/**
 * @author  lz
 *
 * 非空注解使用在方法的参数上false表示此参数可以为空true不能为空
 */
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNotNull {
    boolean value() default false;
}

2.导入测试类

package com.lz.annotation.demo3;

/**
 @author  lz
 * 获取参数修饰注解对应的属性值
 */
public class Demo3 {

    public void hello1(@IsNotNull(true) String name) {
        System.out.println("hello:" + name);
    }

    public void hello2(@IsNotNull String name) {
        System.out.println("hello:" + name);
    }
}
package com.lz.annotation.p3;

import com.lz.annotation.demo3.Demo3;
import com.lz.annotation.demo3.IsNotNull;
import org.junit.Test;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;


/**
 @author  lz
 */
public class Demo3Test {

    @Test
    public void hello1() throws Exception {
        Demo3 demo3 = new Demo3();
        for (Parameter parameter : demo3.getClass().getMethod("hello1", String.class).getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//true
            }
        }
    }

    @Test
    public void hello2() throws Exception {
        Demo3 demo3 = new Demo3();
        for (Parameter parameter : demo3.getClass().getMethod("hello2", String.class).getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//false
            }
        }
    }

    @Test
    public void hello3() throws Exception {
//        模拟浏览器传递到后台的参数 解读@requestParam
        String name = "zs";
        Demo3 demo3 = new Demo3();
        Method method = demo3.getClass().getMethod("hello1", String.class);
        for (Parameter parameter : method.getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//true
                if (annotation.value() && !"".equals(name)){
                    method.invoke(demo3,name);
                }
            }
        }
    }
}

3.测试结果

三. Aop自定义注解的应用

1.导入pom.xml中的依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2.导入自定义注解

package com.lz.annotation.aop;

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

/**
 * 导入自定义注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    String desc();
}

3.编写切面类()

package com.lz.acpect;

import com.lz.annotation.aop.MyLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * LZ
 */
@Component
@Aspect
public class MyLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);

    /**
     * 只要用到了com.javaxl.p2.annotation.springAop.MyLog这个注解的就是目标类
     */
    @Pointcut("@annotation(com.lz.annotation.aop.MyLog)")
    private void MyValid() {
    }

    @Before("MyValid()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        logger.debug("[" + signature.getName() + " : start.....]");
        System.out.println("[" + signature.getName() + " : start.....]");

        MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);
        logger.debug("【目标对象方法被调用时候产生的日志记录到日志表中】"+myLog.desc());
        System.out.println("【目标对象方法被调用时候产生的日志记录到日志表中】" + myLog.desc());
    }
}

4.编写web类用于测试

package com.lz.controller;

import com.lz.annotation.aop.MyLog;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * LZ
 */
@Controller
public class LogController {
    @RequestMapping("/mylog")
    @MyLog(desc = "这是结合spring aop知识讲解自定义注解应用的一个案例")
    public void testLogAspect(){
        System.out.println("这里随便来点啥");
    }
}

5.打印输出的结果web类 

四.总结

注解是Java语言中的一种元数据标记机制用于为程序中的代码、类、方法、变量等元素添加附加信息。在Java中注解主要分为JDK基本注解和JDK元注解两类同时也支持自定义注解。

JDK基本注解包括 @Override、@Deprecated、@SuppressWarningsJDK元注解包括 @Retention、@Target、@Documented、@Inherited。自定义注解需要使用 @interface 关键字进行定义并可以指定元注解和注解属性。

注解在Java中的使用是通过反射机制实现的可以被用于实现各种功能如配置文件的自动读取、代码的自动生成、数据校验、接口的实现等。

在实际应用中可以将注解标记在类、方法、字段等元素上并在运行时通过反射获取注解的信息来实现相应的功能或者结合AOP技术实现对代码的增强。

        到这里我的分享就结束了欢迎到评论区探讨交流

如果觉得有用的话还请点个赞吧

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring
返回列表

上一篇:Linux基本指令

下一篇:Hadoop-Hbase