“高级Java注解的简介及应用“

news2024/11/24 8:01:40

目录

  • 引言
    • 1. Java注解简介
      • 1.1 什么是注解
      • 1.2 注解的作用
      • 1.3 常见的Java注解
    • 2. 自定义注解案例
    • 3. AOP自定义注解的应用
      • 3.1 AOP简介
      • 3.2 AOP自定义注解
    • 总结

在这里插入图片描述

引言

在Java开发中,注解是一种非常重要的语言特性,它们可以为代码提供额外的信息和元数据。本文将介绍Java注解的基本概念,并深入探讨自定义注解和AOP自定义注解的应用。

1. Java注解简介

1.1 什么是注解

注解是一种用于为程序代码添加元数据的方式。它们可以用于描述类、方法、字段等程序元素的特性和行为。Java注解使用@符号作为前缀,并可以包含参数和值。

1.2 注解的作用

提供额外的元数据:注解可以为代码提供额外的信息,如作者、版本号、创建日期等。
编译时检查:注解可以在编译时对代码进行静态检查,以确保代码的正确性和一致性。
运行时处理:注解可以在运行时通过反射机制获取和处理,以实现一些特定的功能。

1.3 常见的Java注解

@Override:用于标识方法覆盖父类的方法。
@Deprecated:用于标识已过时的方法或类。
@SuppressWarnings:用于抑制编译器警告。
@FunctionalInterface:用于标识函数式接口。

  • Java注解分类
JDK基本注解
JDK元注解
自定义注解
  • JDK基本注解
@Override
重写

@SuppressWarnings(value = "unchecked")
压制编辑器警告
  • 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工具提取成文档.
  • 自定义注解
注解分类(根据Annotation是否包含成员变量,可以把Annotation分为两类):

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

元数据Annotation:
包含成员变量的Annotation; 它们可以接受(和提供)更多的元数据;
  • 如何自定义注解?
使用@interface关键字, 其定义过程与定义接口非常类似, 需要注意的是:
   Annotation的成员变量在Annotation定义中是以无参的方法形式来声明的, 其方法名和返回值类型定义了该成员变量的名字和类型,
   而且我们还可以使用default关键字为这个成员变量设定默认值;

2. 自定义注解案例

  • 案例一

demo1

package com.yuan.annotation.demo1;

/**
 *
 * 获取类与方法上的注解值
 */
@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");
    }
}

Demo1Test

package com.yuan.annotation.demo1;

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

MyAnnotation1

package com.yuan.annotation.demo1;

import java.lang.annotation.*;

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

MyAnnotation2

package com.yuan.annotation.demo1;

import java.lang.annotation.*;

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

MyAnnotation3

package com.yuan.annotation.demo1;

import java.lang.annotation.*;

/**
 * MyAnnotation3注解可以用在方法上
 * 注解运行期也保留
 * 可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {
    TranscationModel[] models() default TranscationModel.ReadWrite;
}

TranscationModel

package com.yuan.annotation.demo1;

public enum  TranscationModel {
    Read, Write, ReadWrite
}

测试结果
在这里插入图片描述

在这里插入图片描述

  • 案例二
    Demo2
package com.yuan.annotation.demo2;

/**
 * 获取类属性上的注解属性值
 */
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;
}

Demo2Test

package com.yuan.annotation.demo2;

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());
    }
}

TestAnnotation

package com.yuan.annotation.demo2;

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属性对应的值";
}

  • 案例三
  • IsNotNull
package com.yuan.annotation.demo3;

import java.lang.annotation.*;

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

Demo3

package com.yuan.annotation.demo3;

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

Demo3Test

package com.yuan.annotation.demo3;

import org.junit.Test;

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

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自定义注解的应用

3.1 AOP简介

AOP(面向切面编程)是一种编程范式,它通过将横切关注点(如日志记录、事务管理)从业务逻辑中分离出来,以提高代码的模块化和可维护性。

3.2 AOP自定义注解

我们可以结合AOP和自定义注解,实现在特定方法或类上添加切面逻辑的功能。通过定义一个切面类,并在目标方法上添加自定义注解,可以在运行时动态地执行切面逻辑。
MyLog

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

MyLogAspect

package com.yuan.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);

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

LogController

package com.yuan.web;

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

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

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--1. 注解式开发 -->
    <!-- 注解驱动 -->
    <context:annotation-config/>
    <!-- 用注解方式注入bean,并指定查找范围:com.javaxl.ssh2及子子孙孙包-->
    <context:component-scan base-package="com.yuan"/>
    <!--开启动态代理-->
    <aop:aspectj-autoproxy />

</beans>

在这里插入图片描述

总结

本文介绍了Java注解的基本概念,并详细讨论了自定义注解和AOP自定义注解的应用。通过合理使用注解,我们可以为代码添加更多的元数据,并实现一些特定的功能。注解是Java开发中不可或缺的一部分,希望本文对您有所帮助。
以上是本文的内容,希望能够对您理解高级Java注解的应用有所帮助。感谢阅读!

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

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

相关文章

MFC 绘图

效果图&#xff1a;三张bmp图 字 竖线 组成 在OnPaint()函数中 CPaintDC dc(this);CRect rect;GetClientRect(&rect); //获取客户区矩形CDC dcBmp; //定义并创建一个内存设备环境dcBmp.CreateCompatibleDC(&dc); //创建兼容性DCCBitmap …

如何把利用paddlepaddle导出的json文件转化为yolo或者voc文件

目录 1. 修改源码&#xff0c;让模型能够生成出对于单个图像的标注。 2. 把数据转为yolo格式 3.把yolo格式转化为xml格式 这两天想偷懒&#xff0c;想让模型先在数据上标一遍&#xff0c;然后我再做修正&#xff0c;主要是图个省事。由于我们主要是利用paddle,模型也是基于p…

python+django学习资料在线分享系统vue

本站是一个B/S模式系统&#xff0c;采用vue框架作为开发技术&#xff0c;MYSQL数据库设计开发&#xff0c;充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得校园资料分享平台管理工作系统化、规范化。技术栈 后端&#xff1a;pyth…

同城信息服务源码 本地生活服务小程序源码

同城信息服务源码 本地生活服务小程序源码 功能介绍&#xff1a; 基本设置&#xff1a;网站参数、安全设置、分站管理、支付设置、操作日志、地区设置、公交地铁、国际区号、清理缓存、模板风格、模块管理、域名管理、底部菜单、消息通知、登录设置 其他设置&#xff1a;关键…

Linux内核源码分析 (B.7)深入理解 slab cache 内存分配全链路实现

Linux内核源码分析 (B.7)深入理解 slab cache 内存分配全链路实现 文章目录 Linux内核源码分析 (B.7)深入理解 slab cache 内存分配全链路实现1\. slab cache 如何分配内存2\. slab cache 的快速分配路径3\. slab cache 的慢速分配路径3.1 从本地 cpu 缓存 partial 列表中分配3…

小程序多种姿势更换文章

概述 简单的文章切换demo&#xff0c;通过倒计时、摇一摇、双击进行文章切换 详细 直接看效果图吧&#xff01;比较简单&#xff0c;主要是练习一下... 小程序不带双击事件&#xff0c;可以记录第一次单击事件和第二次单机事件进行双击操作。 1、摇一摇是通过调用官方的 …

将多个元素循环起来构成迭代器itertools.cycle()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将多个元素循环起来 构成迭代器 itertools.cycle() 选择题 以下说法错误的是? import itertools a[1,2,3] print("【显示】a:");print(a) bitertools.cycle(a) print("【执行】…

MVC设计思想理解和ASP.NET MVC理解

三层模式 三层模式包括:UI层,业务逻辑层,数据访问层,模型层 MVC设计思想和ASP.NET MVC理解 MVC设计思想: MVC的思想就是把我们的程序分为三个核心的模块,这三个模块的详细介绍如下: 模型(Model) :负责封装与引用程序的业务逻辑相关的数据以及对数据的处理方法。模型层有对…

Redis 列表操作实战(全)

目录 LINDEX 获取指定下标元素 LSET 指定下标添加元素 LPUSH 将元素插入列表头 LPUSHX RPUSH 将元素插入列表尾 RPUSHX LINSERT 将元素插入列表某位置之前 LLEN 列表长度 LPOP 取列表头元素 RPOP 取列表尾元素 BLPOP 阻塞式取列表头元素 BRPOP 阻塞式取列表尾元素…

精品Python医院挂号信息管理系统

《[含文档PPT源码等]精品基于Python实现的医院挂号信息管理系统》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django 前端技术&#xff1a;JavaScript、…

智能指针解读(2)

前面一篇文章&#xff0c;我讲解了智能指针的原理&#xff0c;并实现了一个简单的智能指针。为了加深对智能指针的理解&#xff0c;在这篇文章中&#xff0c;我把C中的几个智能指针讲解下&#xff1a;auto_ptr, unique_ptr, shared_ptr, weak_ptr。 1、auto_ptr 前面的文章我…

在服务器上创建git仓库

1、在服务器上创建git仓库 选择一个创建文件夹的地方&#xff0c;这个地方不会将源码存放在这里&#xff0c;只用于版本控制 # 创建一个专门放置git的文件夹&#xff0c;也可以叫其它名 mkdir git && cd git # 创建自己项目的文件夹&#xff0c;文件夹后面要带 .git…

电工三级证(高级)实战项目:信号交通灯的PLC控制

实训目的 掌握比较指令掌握时钟指令掌握时间同步的方法 控制要求 PLC设备:Siemens S7-200 要求:按下起动按钮SB1后&#xff0c;东西方向绿灯亮20s&#xff0c;之后再闪烁绿灯3s&#xff0c;之后黄灯亮3s&#xff0c;最后红灯亮26s&#xff1b;同时&#xff0c;南北方向红灯亮…

Winscp--使用技巧

原文网址&#xff1a;Winscp--使用技巧_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Winscp的使用技巧。 保持连接 有时经常自动断开&#xff0c;需要重新连接&#xff0c;解决方法如下&#xff1a; 修改默认目录 每次连接后会自动定位到如下目录&#xff1a;本地Windows的Do…

2023最新安装微信小程序开发软件安装教程

一&#xff0c;安装开发者工具 我们在开发小程序之前&#xff0c;首先需要安装小程序开发者工具&#xff0c;今天就来教大家安装小程序开发者工具。 微信开放文档 (qq.com)https://developers.weixin.qq.com/miniprogram/dev/framework/ 官网工具下载地址&#xff1a; 微信…

Linux 进程相关命令

输入 ps aux后里面有个STAT参数 kill -9 进程ID 或者kill -9 SIGKILL 进程ID强制杀死

76、SpringBoot 整合 MyBatis------使用 sqlSession 作为 Dao 组件(就是ssm那一套,在 xml 写sql)

就是 ssm 那套&#xff0c;在xml 上面写sql ★ 基于SqlSession来实现DAO组件的方式 - MyBatis提供的Starter会自动在Spring容器中配置SqlSession&#xff08;其实SqlSessionTemplate实现类&#xff09;、并将它注入其他组件&#xff08;如DAO组件&#xff09;- DAO组件可直接…

SpringBoot整合Mybatis-Plus分页插件的使用

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;CSDN实力新星&#xff0c;后端开发两年经验&#xff0c;曾担任甲方技术代表&#xff0c;业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…

ExoPlayer实现本地视频播放器

最近单位项目不太忙&#xff0c;决定写个Demo实现一个自己的本地视频播放器&#xff0c;界面参考了完美视频播放器 本地视频播放器 架构简单&#xff0c;功能简单 MVVMkotlinexoplayer实现 当前实现点&#xff1a; 扫描本地视频并以文件夹&#xff08;视频列表&#xff09;形…

Cpp/Qt-day030919Qt

目录 完成文本编辑器的保存工作 头文件&#xff1a;widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QFontDialog> //字体对话框 #include <QFont> //字体类 #include <QMessageBox> //消息对话框 #include <QDe…