SpringMVC:从入门到精通,7篇系列篇带你全面掌握--七.自定义注解

news2024/12/25 8:55:31

目录

🥳🥳Welcome Huihui's Code World ! !🥳🥳

一.Java注解简介

1.原生注解的分类

(1)JDK基本注解

        ①@Override

        ②@SuppressWarnings(value = "unchecked")

(2)JDK元注解

        ①@Retention

        ②@Target

        ③@Source

        ④@Inherited

(3)自定义注解

        ①标记注解

        ②元数据注解

2.如何自定义注解

二.自定义注解的各种使用情况

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

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

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

三.AOP结合自定义注解完成案例 

1.自定义注解

①使用@interface关键字定义注解接口

②为注解添加元素(可选)

③使用元注解(如@Retention、@Target等)对注解进行配置

2.应用注解


🥳🥳Welcome Huihui's Code World ! !🥳🥳

接下来看看由辉辉所写的关于SpringMVC的相关操作吧

一.Java注解简介

        Java注解(Annotation)是一种用于描述代码的元数据,它可以用于为代码提供额外的信息,以便在编译、运行时或者其他阶段对代码进行处理。注解不会影响代码的实际逻辑,仅作为一种标记。Java注解可以应用于类、方法、变量、参数等元素

1.原生注解的分类

(1)JDK基本注解

下面介绍两种常用的JDK元原生注解

        ①@Override

             @Override是Java中的一个注解,用于表示一个方法是重写了父类的方法。当一个方法被标注为@Override时,编译器会检查该方法是否正确地重写了父类的方法。如果没有正确地重写父类的方法,编译器会报错

        ②@SuppressWarnings(value = "unchecked")

             @SuppressWarnings是Java中的一个注解,用于告诉编译器忽略指定的警告信息。这个注解通常用于处理代码中的某些问题,例如类型转换警告、未经检查的异常等

             @SuppressWarnings注解有以下几种用法:

                ①@SuppressWarnings(value = "unchecked"):忽略未经检查的异常警告。

                ②@SuppressWarnings(value = {"unchecked", "deprecation"}):忽略未经检查的                        异常和已弃用的警告。

                ③@SuppressWarnings("unchecked"):忽略未经检查的异常警告。

                ④@SuppressWarnings({"unchecked", "deprecation"}):忽略未经检查的异常和已                         弃用的警告

public class SuppressWarningsExample {
    public static void main(String[] args) {
        // 使用@SuppressWarnings注解忽略未经检查的异常警告
        @SuppressWarnings("unchecked")
        void myMethod() {
            List rawList = new ArrayList();
            List<String> stringList = rawList; // 这里会产生未经检查的异常警告
        }
    }
}

(2)JDK元注解

        ①@Retention

@Retention:定义注解的保留策略
@Retention(RetentionPolicy.SOURCE)             //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)              //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME)            //注解会在class字节码文件中存在,在运行时可以通过反射获取到

        ②@Target

@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}),也就是此注解可以在方法和类上面使用

        ③@Source

@Inherited:指定被修饰的Annotation将具有继承性

        ④@Inherited

@inherited 注解用于指示子类是否继承父类的注解。当在父类上使用了 @inherited 注解时,子类会自动继承该注解。但要注意,@inherited 注解仅适用于类级别的注解,对于方法、字段等其他元素级别的注解不起作用

@Documented:指定被修饰的该Annotation可以被javadoc工具提取成文档.

(3)自定义注解

根据Annotation是否包含成员变量,可以把Annotation分为两类

        ①标记注解

没有成员变量的Annotation; 这种Annotation仅利用自身的存在与否来提供信息

        ②元数据注解

包含成员变量的Annotation; 它们可以接受(和提供)更多的元数据

2.如何自定义注解

使用@interface关键字, 其定义过程与定义接口非常类似, 需要注意的是:
   Annotation的成员变量在Annotation定义中是以无参的方法形式来声明的, 其方法名和返回值类型定义了该成员变量的名字和类型,
   而且我们还可以使用default关键字为这个成员变量设定默认值(这里只是简略见一下,后面会结合案例详细讲解自定义注解的步骤)

二.自定义注解的各种使用情况

需要的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zking</groupId>
    <artifactId>spboottest01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spboottest01</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
<!--            <scope>test</scope>-->
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

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

package com.wh.annotation;

public enum  TranscationModel {
    Read, Write, ReadWrite
}
package com.wh.annotation.pi;

import java.lang.annotation.*;

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

import com.wh.annotation.TranscationModel;

import java.lang.annotation.*;

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

import com.wh.annotation.TranscationModel;

import java.lang.annotation.*;

/**
 * @author 小李飞刀
 * @site www.javaxl.com
 *
 * MyAnnotation3注解可以用在方法上
 * 注解运行期也保留
 * 可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {
    TranscationModel[] models() default TranscationModel.ReadWrite;
}
package com.wh.annotation.demo;

import com.wh.annotation.TranscationModel;
import com.wh.annotation.pi.MyAnnotation1;
import com.wh.annotation.pi.MyAnnotation2;
import com.wh.annotation.pi.MyAnnotation3;


@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.wh.annotation.demo;

import com.wh.annotation.TranscationModel;
import com.wh.annotation.pi.MyAnnotation1;
import com.wh.annotation.pi.MyAnnotation2;
import com.wh.annotation.pi.MyAnnotation3;
import org.junit.Test;


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
        }
    }
}

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

package com.wh.annotation.p2;

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


//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
    String value() default "默认value值";

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

测试

package com.wh.annotation.demo2;

import com.wh.annotation.p2.TestAnnotation;


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.wh.annotation.demo2;

import com.wh.annotation.p2.TestAnnotation;
import org.junit.Test;


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.获取参数修饰注解对应的属性值

package com.wh.annotation.p3;

import java.lang.annotation.*;

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

import com.wh.annotation.p3.IsNotNull;

/**

 *
 * 获取参数修饰注解对应的属性值
 */
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);
    }
}

三.AOP结合自定义注解完成案例 

1.自定义注解

①使用@interface关键字定义注解接口

package com.wh.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();
}

②为注解添加元素(可选)

③使用元注解(如@Retention@Target等)对注解进行配置

package com.wh.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();
}
package com.wh.annotation.aop;

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;

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

    /**
     * 只要用到了com.javaxl.p2.annotation.springAop.MyLog这个注解的,就是目标类
     */
    @Pointcut("@annotation(com.wh.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());
    }
}

2.应用注解

package com.wh.annotation.aop;

import org.springframework.stereotype.Component;


@Component
public class LogController {

    @MyLog(desc = "这是结合spring aop知识,讲解自定义注解应用的一个案例")
    public void testLogAspect(){
        System.out.println("这里随便来点啥");
    }
}
package com.wh.annotation.aop;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author 小李飞刀
 * @site www.javaxl.com
 */
public class LogControllerTest {
    @Autowired
    private LogController logController;

    @Test
    public void testLogAspect(){
        logController.testLogAspect();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1009996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Golang goroutine MPG模式浅析

协程是通过使用关键字 go 调用&#xff08;或执行&#xff09;一个函数或者方法来实现的&#xff08;也可以是匿名函数&#xff09;。 Go 语言在语言层面上支持了并发&#xff0c;goroutine是Go语言提供的一种用户态线程&#xff0c;有时我们也称之为协程。 所谓的协程&#x…

Generative Adversarial Nets

Author:龙箬 Computer Application Technology Change the World with Data and Artificial Intelligence ! CSDNweixin_43975035 生命不息&#xff0c;折腾不止 Reference&#xff1a; [1] Goodfellow, I, Pouget-Abadie, J, Mirza, M, Xu, B, Warde-Farley, D, Ozair, S, Co…

《优化接口设计的思路》系列:第一篇—接口参数的一些弯弯绕绕

大家好&#xff01;我是sum墨&#xff0c;一个一线的底层码农&#xff0c;平时喜欢研究和思考一些技术相关的问题并整理成文&#xff0c;限于本人水平&#xff0c;如果文章和代码有表述不当之处&#xff0c;还请不吝赐教。 作为一名从业已达六年的老码农&#xff0c;我的工作主…

PSP - 蛋白质序列提取 Transformer 蛋白质语言模型 ESM2 特征

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132888139 蛋白质语言模型 ESM (Evolutionary Scale Modeling) 是一种利用深度学习技术来预测蛋白质结构和功能的方法。ESM 通过在大规模的蛋白质…

激光雷达检测负障碍物(附大概 C++ 代码)

检测效果如图&#xff0c;红色是正负的障碍物点&#xff1a; 障碍物根据其相对于地面的高度可以分为两类&#xff1a;正向障碍物和负向障碍物。在室外环境中&#xff0c;负障碍物是沟渠、悬崖、洞口或具有陡峭负坡度的地形&#xff0c;可能会造成安全隐患。 不慎通过道路坑洼处…

【电子通识】案例:采用电阻分压式采样电压的设计注意事项

在一些应用中,我们往往采用电阻分压方式来采样外部电压。如文章【Arduino+ESP32专题】案例:简单的实现NTC热敏电阻检测板卡温度中我们就使用一个10K的电阻与NTC电阻形成分压,通过ADC读取到的电压换算成温度值来检测外部环境温度。 当然,比如手持机的电池电压,如果没有一些…

docker-compose 中 depends_on 的作用

文章目录 depends_on 介绍depends_on 有一个长定义模式condition 说明required 说明 参考文档 depends_on 介绍 在 Docker Compose 中&#xff0c;depends_on 是一个用于定义服务之间依赖关系的关键字。它允许您指定一个或多个服务依赖于其他服务&#xff0c;以确保在启动或重…

基于STM32F407ZET6的环境温湿度监控系统(粤嵌GEC-M4)

注意使用事项&#xff1a; 开发板如下 由于外部晶振是8M&#xff0c;需要修改setup和stm32f4头文件的晶振值。 操作如下&#xff1a; system_stm32f4xx.c的254行 #define PLL_M 8stm32f4xx.h的127行 #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the Ex…

实战SRC漏洞挖掘全过程,流程详细【网络安全】

前言 记录一次完整的某SRC漏洞挖掘实战&#xff0c;为期一个多星期。文章有点长&#xff0c;请耐心看完&#xff0c;记录了完整的SRC漏洞挖掘实战 渗透过程 因为选择的幸运儿没有对测试范围进行规划&#xff0c;所以此次范围就是没有范围。 先上主域名看一眼&#xff0c;看…

2023 Google 开发者大会 – AI 领域的技术更新

大会介绍 Google 开发者大会是 Google 面向开发者和科技爱好者展示最新产品和平台的年度盛会。2023 Google 开发者大会 (Google I/O Connect | China) 为开发者提供丰富的学习资源&#xff0c;实践操作和现场演示&#xff0c;提供与谷歌专家互动、与其他开发者交流的契机&…

贝锐蒲公英客户端6.0发布,异地组网更快、更简单

贝锐蒲公英客户端6.0全新升级&#xff0c;新版本融合了企业版、个人版和个人管理端&#xff0c;不同身份用户可以统一登录&#xff0c;快速部署&#xff0c;即装即用&#xff0c;为异地组网带来更加简单、高效的解决方案。 快速部署、即装即用&#xff0c;支持不同身份用户统一…

langchain主要模块(三):Chain

langchain2之Chain langchain1.概念2.主要模块模型输入/输出 (Model I/O)数据连接 (Data connection)链式组装 (Chains)代理 (Agents)内存 (Memory)回调 (Callbacks) 3.链• LLMChain&#xff1a;• SimpleSequentialChain• Sequential Chains:• RouterChain&#xff1a; lan…

社群团购平台方的选品,无外乎就几个方面:

社群团购平台方选品&#xff0c;无外乎几个方面&#xff1a; 1、是个主推广爆品&#xff0c;好产品&#xff08;好产品的标准&#xff1a;有卖点&#xff1a;比如&#xff1a;有 品牌力、市场需求力、诱人的性价比等&#xff09; 2、你是否跟社群团购平台方说清楚这个产品的优…

什么是云存储,从对象存储说起?

在《存储系统形态之争,从块存储到统一存储》一文中我们提到了对象存储的概念,知道目前很多企业级存储都是支持对象存储的,比如EMC、NetApp和华为等。以EMC的对象存储为例,其最早在1998年就已经具备成熟的产品了,到目前已经有二十多年的历史了。如图是关于对象存储主要产品…

科研诚信与学术规范MOOC-错题集

为了确保学术和科研诚信&#xff0c;很多大学制定了荣誉法则。大学建立荣誉制度的初衷旨在预防大学生考试作弊。“反相对论公司”是对科学的不当干预。&#xff08;√&#xff09;科学具有普遍性&#xff0c;与种族、国籍、宗教、阶级和个人品质等个人因素无关。&#xff08;不…

GpsModule 350+ 常用GPS坐标地图

背景 开源库 GpsAndMap 的 GpsModule 模块中整理集成了 350 国内常用地市的GPS坐标地址&#xff0c;对于日常使用&#xff0c;例如打些标记&#xff0c;做些PPT展示&#xff0c;是非常方便的。 引入模块 pip install GpsAndMap 打印常用地市GPS地名清单 以下代码打印了常用…

【业务功能109】微服务-springcloud-springboot-Skywalking-链路追踪-监控

Skywalking skywalking是一个apm系统&#xff0c;包含监控&#xff0c;追踪&#xff0c;并拥有故障诊断能力的 分布式系统 一、Skywalking介绍 1.什么是SkyWalking Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的产品&#xff0c;它同时吸收了Zipkin /Pinpoint …

力扣 -- 1218. 最长定差子序列

参考代码&#xff1a; class Solution { public:int longestSubsequence(vector<int>& arr, int difference) {int narr.size();unordered_map<int,int> hash;//nums[i]绑定dp[i]hash[arr[0]]1;int ret1;for(int i1;i<n;i){int aarr[i];int ba-difference;…

电力系统安全问题,金融行业需警惕!

在现代金融业务的快速发展中&#xff0c;电力供应的可靠性变得愈发重要。金融交易和数据处理依赖于持续的电力供应&#xff0c;任何电力中断都可能导致严重的业务中断和损失。 为了应对这一挑战&#xff0c;金融机构广泛采用了不间断电源&#xff08;UPS&#xff09;系统&#…

QT 连接SQLServer数据库

1、安装SQLServer数据库后 在SQL Server 配置管理器中 设置后&#xff0c;需要重新启动SQL Server服务 2、重点* 配置ODBC数据源 由于没有配置ODBC&#xff0c;一直无法连接 开始——ODBC数据源管理程序(64位) 之后选择&#xff1a;使用用户输入登录ID和密码的SQL Server验…