【Java笔记】如何创建自己的注解+注解怎么用于反射+SpringBoot常见注解

news2024/12/27 9:45:46

文章目录

  • 0. 为什么SpringBoot要整这么多注解?
  • 1. 一些基础知识
    • 1.1 什么是注解
    • 1.2 Java内置注解
      • 1.2.1 作用在代码上的注解
      • 1.2.2 作用在注解的注解(元注解)
      • 1.2.3 Java 7之后的新注解
    • 1.3 注解的作用
    • 1.4 如何实现一个自己的注解?
      • 1.4.1定义自己的注解
      • 1.4.2 使用自定义注解实现运行时调用
  • 2. SpringBoot常见注解
    • 2.1 IOC于DI相关
      • 2.1.1 IOC相关
      • 2.1.2 DI相关
    • 2.2 SpringBoot启动类中
    • 2.3 Controller中
      • 2.3.1 Controller参数接收
      • 2.3.2 Controller响应数据
      • 2.3.3 Controller请求绑定
  • Reference

复习笔记,个人记录用,有问题欢迎指出

0. 为什么SpringBoot要整这么多注解?

说白了就是为了方便,SpringBoot通过注解维护各种 Bean 组件的简化开发流程的各种配置(也就是方便自动装配)。
下面我们暂时跳出SpringBoot框架,稍微回顾一下基础的Java常用注解跟一些基础知识。

1. 一些基础知识

1.1 什么是注解

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。

注解就是我们平常看到的@开头的玩意儿,有时候加载方法上,有时候又会加在类、变量、参数上。别的注解没见过,那@Override总见过吧?这就是Java内置的注解之一。

1.2 Java内置注解

1.2.1 作用在代码上的注解

  • @Override:作用在方法上,检查该方法是否是重写方法,如果父类中没有这个方法(即尝试重写父类不存在的方法),编译时会报错。 当然,重写的方法并不是一定要加 @Override,这不是必须的。
  • @Deprecated : 作用在方法上,标记过时方法。如果使用该方法,会报编译警告。
  • @SuppressWarnings:指示编译器去忽略注解中声明的警告。

1.2.2 作用在注解的注解(元注解)

  • @Retention:定义注解的保留策略,也就是标识这个注解怎么保存
    • @Retention(RetentionPolicy.SOURCE):注解仅存在于源码中,在class字节码文件中不包含;
    • @Retention(RetentionPolicy.CLASS) :注解会在class字节码文件中存在,但运行时无法获得(默认的保留策略);
    • @Retention(RetentionPolicy.RUNTIME):注解会在class字节码文件中存在,在运行时可以通过反射获取到。
  • @Target - 标记这个注解可以修饰的目标
    • @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) :包
  • @Inherited - 指定被修饰的Annotation将具有继承性
  • @Documented - 标记这些注解能否被包含在javadoc中
    • javadoc就是我们看源码时看到的那些API注释,比如@Param

1.2.3 Java 7之后的新注解

  • @SafeVarargs :忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告(Java 7)
  • @FunctionalInterface:标识一个匿名函数或函数式接口(Java 8)
    • 有兴趣可以了解下Lambda表达式相关,也是Java8的新特性,简单来说就是提供了更便利的函数式编程的方式,前提就是需要有一个函数式接口。
  • @Repeatable:标识某注解可以在同一个声明上使用多次(Java 8)

1.3 注解的作用

长话短说:

  1. 编译时检查,比如 @Override@Deprecated之类的。
  2. 反射中使用,比如我们可以通过注解过滤得到想invoke的method
  3. 帮助理解代码,这个就比较抽象了,只能说能帮我们理解整体的框架。

稍微啰嗦两句, 使用注解能带来很多便利,帮我们省去很多繁琐的实现细节(比如Springboot的自动装配、依赖注入等等),但同时,对于不太了解相关注解的朋友来说反而更不好理解这些细节,办法也很简单,面试经典-读过XXX源码吗?

1.4 如何实现一个自己的注解?

1.4.1定义自己的注解

大概格式如下

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}

可以看到用了几个元注解

  • @Retention(RetentionPolicy.RUNTIME):注解会在class字节码文件中存在,在运行时可以通过反射获取到;
  • @Target(ElementType.METHOD):注解可以加在函数方法上;
  • @Documented:可有可无,希望加入javadoc就加上。
  • 如果希望自定义注解在类的继承关系中可以传递,那也可以加上@Inherited

我们也可以给注解绑定一些数据:

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String name() default "Hansdas";
    String value();
}

其中,default可以指定默认值

1.4.2 使用自定义注解实现运行时调用

public class MyClass {
    public MyClass() {
    }

    @MyAnnotation(name = "Hansbas", value = "114514")
    public void MyMethod1(){
        System.out.println("Method1 used");
    }

    public void MyMethod2(){
        System.out.println("Method2 used");
    }
}

我们在MyMethod1上面加了自定义注解,在Method2上面没加,下面尝试通过反射的方式来在运行时获得Method1:

public class Test {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, ClassNotFoundException {
        // 一般需要把new的对象交给一个container管理,这里省事直接new了
        MyClass myClass = new MyClass();
        // 下面通过反射调用方法
        String className = "Annotation.MyClass";
        Class<?> clazz = Class.forName(className);
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods){
            if(method.getDeclaredAnnotation(MyAnnotation.class) != null){
                method.invoke(myClass);
                MyAnnotation myAnno = method.getDeclaredAnnotation(MyAnnotation.class);
                System.out.println("name: "+myAnno.name()+", value: "+myAnno.value());
            }
        }
    }
}

结果如下,method1成功获得,并且成功获得了注解的各个属性值,而method2被过滤了
在这里插入图片描述

2. SpringBoot常见注解

上一节讲了Java中的一些基础注解,以及如何创建自己的注解并用于反射机制实现运行时调用。接下来理一下SpringBoot里常见的一些注解。

2.1 IOC于DI相关

IOC就是讲对象的创建与管理交给Spring容器管理,DI依赖注入则是调用容器中的Bean实例,二者都涉及到了很多注解来方便我们使用

2.1.1 IOC相关

  • @Component:表明一个类会作为组件类,并告知Spring要为这个类创建bean,交给IOC容器管理,也是最基础的一个注解,包含很多衍生类:

    注解说明位置
    @Component表明一个类会作为组件类,并告知Spring要为这个类创建bean不属于下面三类时用(比如一些工具类)
    @Controller标记的类就是一个SpringMVC Controller对象,分发处理器会扫描使用该注解的类的方法,并检测该方法是否使用了@RequestMapping注解。标注在控制器上(Controller层的bean对象)
    @Service应用于业务层,用于标注业务层组件,表示定义一个bean,自动根据bean的类名实例化一个首写字母为小写的bean。标注在业务类上Service层的bean对象)
    @Repository只能标注在 DAO 类,除了将该类标记为bean以外,还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。标注在数据访问类上(Dao层的bean对象,由于与mybatis整合,用的少)
  • @Lazy :Spring在应用程序上下文启动时去创建所有的单例bean对象, 而@Lazy注解可以延迟加载bean对象,即在使用时才去初始化,好处包括:

    • 可以减少Spring的IOC容器启动时的加载时间
    • 可以解决bean的循环依赖问题
  • @Scope() :声明bean的作用域,常见的包括singleton、prototype等等

    • singleton 容器内同 名称 的 bean 只有一个实例(单例)(默认)
    • prototype 每次使用该 bean 时会创建新的实例(非单例)

另外需要注意的是,@Component时需要我们加在希望作为bean的类上的,但是如果bean来自第三方依赖,那就无法修改了,也就是不能使用@Component,这时候就需要通过配置类来将其交给IOC容器,涉及到的注解有:

  • @Configuration:声明配置类,类中写一个方法返回目标对象。底层也是@Component ,在项目启动时会生成一个bean
  • @Bean:声明第三方bean
  • @Import:可以导入带有@Configuration的配置类。只有使用@Import导入的类才会被Spring加载到IOC容器中!(不然Configuration就白整了)
//----------配置类----------
@Configuration
public class CommonConfig {
    @Bean
    public SAXReader saxReader(){
        return new SAXReader();
    }
}
//----------启动类----------
@Import({CommonConfig.class})
@SpringBootApplication
public class SpringbootWebConfig2Application {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebConfig2Application.class, args);
    }
}
//----------测试注入---------
class xxApplicationTests {
    @Autowired
    private SAXReader saxReader; //IOC容器对象,默认是方法名小写
    //获取bean对象
    @Test
    public void testGetBean(){
       ...
    }
}

2.1.2 DI相关

经典面试问题:@Autowired与@Resource的区别:
@Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
@Autowired 默认是按照类型注入,而@Resource是按照名称注入

  • @Autowired:默认按照类型进行,如果容器中存在多个相同类型的bean,会报错
    • @Primary:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现
  • @Resource:是按照bean的名称进行注入,但这个严格来说是JDK提供的

2.2 SpringBoot启动类中

@SpringBootApplication :标记为启动类,Spring Boot 会运行这个类的 main 方法来启动 Spring Boot 应用。源码如下

@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 {
...

可以看到里面包含了前面提到的一些元注解:

  • @Target({ElementType.TYPE}):前面提到过的元注解之一,声明注解可以加在类上;
  • @Retention(RetentionPolicy.RUNTIME):前面提到过的元注解之一,注解存在于字节码文件,且能运行时获得;
  • @Documented:前面提到过的元注解之一,加入javadoc;
  • @Inherited:前面提到过的元注解之一,标记注解能否被继承继承,如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解;

以及其他的一些Spring相关注解

  • @SpringBootConfiguration@Configuration的封装
    • @Configuration声明一个配置类,底层也是@Component ,在项目启动时会生成一个bean;
  • @EnableAutoConfiguration:开启SpringBoot自动配置,简化Spring原先繁琐的XML配置,加快开发效率;
  • @ComponentScan:自动扫描当前包及其子包下标注了@Component@Controller@Service@Repository 类,并加入spring容器管理。

2.3 Controller中

Controller,当然是需要@Controller来声明这个Controller类可以交给IOC容器管理
此外,Controller中由于涉及到请求的解析与返回,对于请求处理、输入数据与返回数据也有一些常见的注解。

2.3.1 Controller参数接收

  • @RequestParam:参数名与形参变量名相同,定义形参即可接收参数,过程中会自动类型转换,对不上则就收不到,为null,此时可以用RequestMapping

  • @DateTimeFormat:完成日期格式转换

  • @PathVariable:路径参数

  • @RequestBody:将HTTP请求体中的JSON装配到目标类

2.3.2 Controller响应数据

  • @ResponseBody:作用在Controller方法/类上,返回return的结果,如果是实体类则返回json

  • @CrossOrigin:来开启跨域请求,让其他域的请求可以访问该controller,属性包括:

    • origin属性:允许可访问的域列表
    • maxAge属性:准备响应前的缓存持续的最大时间(以秒为单位)

2.3.3 Controller请求绑定

首先,需要@RequestMapping绑定url路径到当前controller上,一般用于获得整个controller各个函数的公共路径
然后是根据HTTP请求类型绑定到对应函数:

  • @GetMapping:处理Get请求
  • @PostMapping:处理Post请求,新增操作
  • @PutMapping:处理put请求,执行大规模的替换操作(而不是更新操作)
  • @DeleteMapping:处理delete请求,删除
  • @PatchMapping:处理patch请求,对资源数据打补丁或局部更新

举个简单的例子(来自黑马的Spring基础教程)

@RestController
@RequestMapping("/depts") // 抽取公共请求路径
public class DeptController {
	@GetMapping
    public Result list(){
        // 部门列表查询,调用对应的service
        List<Dept> deptList = deptService.list();
        return Result.success(deptList);
    }
    
    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id){
        // 调用对应的service根据ID查找部门
        Dept dept = deptService.getById(id);
        return Result.success(dept);
    }
    
    @DeleteMapping("/{id}")
    // - `@PathVariable` :接收路径参数
    //- `@DeleteMapping` :删除注解
    public Result delete(@PathVariable Integer id) throws Exception{
        // 调用service删除部门
        deptService.delete(id);
        log.info("根据id删除部门:{}",id);
        return Result.success();
    }

	@PostMapping
    public Result add(@RequestBody Dept dept){
        // 调用service新增部门
        deptService.add(dept);
        return Result.success();

    }
}

Reference

Java项目的程序里为什么老用注解?注解有哪些作用
Java 注解(Annotation)
一文搞懂🔥SpringBoot自动配置原理
【Java笔记】Reflection的一个实践(模拟框架的服务管理与服务注入)

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

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

相关文章

向量的求导

参考&#xff1a; 向量的求导 向量内积求导

如何提交已暂存的更改到本地仓库?

文章目录 如何提交已暂存的更改到本地Git仓库&#xff1f;步骤1&#xff1a;确认并暂存更改步骤2&#xff1a;提交暂存的更改到本地仓库 如何提交已暂存的更改到本地Git仓库&#xff1f; 在Git版本控制系统中&#xff0c;当你对项目文件进行修改后&#xff0c;首先需要将这些更…

Diffusion Model原理剖析

目录 前言1. DDPM演算法初览2. 图像生成模型共同目标3. VAE: Lower bound of l o g P ( x ) logP(x) logP(x)4. Diffusion Model背后的数学原理5. 为什么需要Sample?6. Diffusion Model的应用7. Diffusion Model成功的关键总结参考 前言 接着上篇文章 图像生成模型浅析&#…

四川古力未来科技抖音小店:科技新宠,购物新选择

在数字化浪潮席卷全球的今天&#xff0c;电商行业日新月异&#xff0c;新兴平台层出不穷。四川古力未来科技抖音小店&#xff0c;作为其中的佼佼者&#xff0c;凭借其独特的魅力和创新的服务模式&#xff0c;正逐渐成为消费者眼中的购物新宠。 一、四川古力未来科技抖音小店的独…

深度卷积神经网络的整体运行流程(以alexnet为例)

0.基础概念&#xff08;复习一下&#xff09; 1.小批量随机梯度下降 目的&#xff1a; 希望找到最佳的参数&#xff0c;使损失函数最小。 使损失函数对w求导&#xff08;b就是x等于1的w&#xff09;&#xff0c;一个小批次的/eta&#xff08;学习率&#xff09;*小批次的平均…

2024团体设计天梯赛之L1-101 别再来这么多猫娘了

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

上市公司数字化转型速度测-含代码及原始数据(2000-2022年)

数据来源&#xff1a;Wind数据库、企业年报时间跨度&#xff1a;2000-2022年 其中吴非、赵宸宇版本的数据是从2000到2022年&#xff1b;袁淳版本和李瑛玫版本的数据均是从2001-2022年。数据范围&#xff1a;上市公司数据指标&#xff1a;计算了三份测算数字化转型速度的数据。其…

Java中的构造器

即使在类中什么都不写也会自动的生成一个构造器 注意 使用new关键字是在调用构造器 如果定义了有参构造 那么就不会默认的走Person person new Person();如果没有自己手动的定义无参构造就不能使用 在idea中 用按键Altinsert可以快速生成有参、无参构造&#xff08;某些品牌的…

yolov8-obb旋转目标检测详细流程

一、数据标注 由于旋转目标标注与传统的目标检测标注有一定的区别&#xff0c;故使用roLabelImg或者labelimg2进行标注&#xff0c;以下标注软件选用的是roLabelImg。 roLabelImg下载地址&#xff1a;https://github.com/cgvict/roLabelImg 直接在原有的labelimg环境中使用roL…

宝塔面板国际版aaPanel 精简版安装

宝塔面板国际版aaPanel 精简版安装 很多人都知道宝塔面板&#xff0c;但不知道宝塔面板还有英文版&#xff0c;宝塔面板英文版不是单纯的宝塔面板的翻译&#xff0c;而是根据老外的使用习惯及国外的网络环境做了一定的优化&#xff0c; 比如&#xff1a;去掉了手机号验证、去…

关于淘宝API接口请求数据的靠谱方式,主要包括以下几个方面:

关于淘宝API接口请求数据的靠谱方式&#xff0c;主要包括以下几个方面&#xff1a; 了解API接口和请求方式&#xff1a; API接口采用通用的HTTP协议&#xff0c;支持GET、POST等多种请求方式。GET方法主要用于向指定资源发出请求并返回实体主体内容&#xff0c;如查询、菜单列…

PBR相关基础知识

文章目录 **核心理念****关键组件与参数****工作流程****优势****挑战与注意事项**实例展示 基于物理的渲染&#xff08;Physically Based Rendering, PBR&#xff09;是一种现代计算机图形学技术&#xff0c;它致力于通过模拟真实世界中光与物质相互作用的物理规律来生成高度逼…

JAVA学习笔记30(线程)

1.线程 1.线程的概念 1.线程是由进程创建的&#xff0c;是进程的一个实体 2.一个进程可以拥有多个线程 2.并发 ​ *同一时刻&#xff0c;多个任务交替执行&#xff0c;造成一种"貌似同时"的错觉&#xff0c;单核cpu实现的多任务就是并发 3.并行 ​ *同一时刻&…

Python的round与Excel的round不一样?

Python四舍五入怎么做 round()奇进偶舍round函数既不是“四舍五入”的原则&#xff0c;也不是“四舍六入无成双”的原则。 decimal round() 偶然发现python的round函数和excel的round函数对某些数据的处理结果不一致。有看到博主提到是奇进偶舍的方法&#xff0c;但经过验证和…

elementUi 日期选择器 组件禁止手输

添加:editable"false" <el-date-pickerv-model"formInline.EndTime"type"datetime"placeholder"选择结束时间"format"YYYY-MM-DD HH:mm:ss"value-format"YYYY-MM-DD HH:mm:ss":editable"false">&…

0 transformers入门,HuggingFace!

目录 1 了解 2 文本分类 1 了解 1 依赖安装 !pip install transformers -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 2 了解transformers 能做什么 from transformers.pipelines import SUPPORTED_TASKS SUPPORTED_TASKS.items()2 文本分类 我没外网所以…

[2024更新]如何从Android恢复已删除的相机照片?

相信大家都经历过Android手机误删相机图片的经历。您是否正在寻找一种可行的方法来挽救这些丢失的照片&#xff1f;如果这是你迫切想解决的问题&#xff0c;那么这篇文章绝对可以帮助你。然而&#xff0c;与其考虑如何从Android恢复已删除的相机照片&#xff0c;我们更愿意建议…

3D模型人物换装系统(五 模型核批之后模型uv不正确)模型UV不正确

3D模型人物换装系统&#xff08;五 模型核批之后模型uv不正确&#xff09;模型UV不正确 介绍展示Maya导入查看uvUnity中测试分析没合批为什么没有问题总结 介绍 最近在公司里给公司做模型优化合批的时候发现了模型的uv在合批之后无法正常展示&#xff0c;这里找了很多的原因&a…

【竞技宝】中超:泰山队4比1大胜沧州雄狮,费南多独造三球

泰山队在本轮中超主场跟沧州雄狮相遇,这场比赛开打前球迷都觉得主队不好踢。因为,沧州雄狮是中超大黑马,整体战绩可圈可点。另外,泰山队则是境遇不佳,主帅崔康熙饱受球队伤病不断的困扰。最让山东球迷觉得郁闷的是崔康熙上一轮因质疑马宁吹罚,还直接罚到了看台。这就意味着崔康…

2024.4.21周报

目录 摘要 Abstract 文献阅读&#xff1a;Next Item Recommendation with Self-Attentive Metric Learning 问题及方法 论文贡献 方法论 序列感知的推荐系统 神经注意模型 模型&#xff1a;ATTREC 序列推荐 基于Self-Attention的用户短期兴趣建模 用户长期兴趣建模…