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

文章目录

  • 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就加上。
    我们也可以给注释绑定一些数据:
@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 {@Beanpublic 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 {@Autowiredprivate SAXReader saxReader; //IOC容器对象,默认是方法名小写//获取bean对象@Testpublic 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 {@GetMappingpublic Result list(){// 部门列表查询,调用对应的serviceList<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();}@PostMappingpublic Result add(@RequestBody Dept dept){// 调用service新增部门deptService.add(dept);return Result.success();}
}

Reference

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JVM系列】关于静态块、静态属性、构造块、构造方法的执行顺序

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

K-means和DBSCAN

目录 一、K-means和DBSCAN之间的主要区别 二、DBSCAN聚类算法 2.1DBSCAN聚类算法实现点集数据的聚类 2.2DBSCAN聚类算法实现鸢尾花数据集的聚类 三、K-means聚类算法 3.1K-means聚类算法实现随机数据的聚类 3.2K-means聚类算法实现鸢尾花数据集的聚类 一、K-means和DBSC…

【大数据】TiDB: A Raft-based HTAP Database

文章目录 数据库知识介绍数据库系统的ACID特性分布式系统和CAP理论关系型数据库与非关系型数据库关系型数据库非关系型数据库 OldSQL、NoSQL、NewSQLOldSQLNoSQLNewSQL OLTP、OLAP、HTAP 前言&#xff1a;为什么选择TiDB学习&#xff1f;pingCAP介绍TiDB介绍TiDB的影响力TiDB概…

【C】 初识C语言

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C语言从入门到精通⏪   &#x1f69a;代码仓库:C语言初级&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 目录 前言 1. 什么是C语言&#…

STM32学习和实践笔记(14):按键控制实验

消除抖动有软件和硬件两种方法 软件方法就是在首次检测到低电平时加延时&#xff0c;通常延时5-10ms&#xff0c;让抖动先过去&#xff0c;然后再来检测是否仍为低电平&#xff0c;如果仍然是&#xff0c;说明确实按下。 硬件方法就是加RC滤波电路&#xff0c;硬件方法会增加…

Linux - Docker 安装 Nacos

拉取 Nacos 镜像 使用以下命令从 Docker Hub 拉取最新版本的 Nacos 镜像&#xff1a; docker pull nacos/nacos-server启动 Nacos 容器 使用以下命令启动 Nacos 容器&#xff1a; docker run -d \--name nacos \--privileged \--cgroupns host \--env JVM_XMX256m \--env M…

Git:使用conda命令切换虚拟环境

1. 问题 在win10电脑的Git中&#xff0c;无法使用conda list命令&#xff0c;报错&#xff08;bash&#xff1a;conda&#xff1a;command not found&#xff09;。也无法使用conda activate base命令激活虚拟环境&#xff0c;报错&#xff08;bash&#xff1a;conda&#xff…

python免费调用阿里云通义千问(q-wen-max)大模型API

文章目录 通义千问开通免费API Keypython调用阿里云通义千问API 通义千问 通义千问&#xff0c;是基于阿里巴巴达摩院在自然语言处理领域的研究和积累。采用更先进的算法和更优化的模型结构&#xff0c;能够更准确地理解和生成自然语言、代码、表格等文本。 支持更多定制化需…

深度学习500问——Chapter08:目标检测(2)

文章目录 8.2.4 R-FCN 8.2.5 FPN 8.2.6 Mask R-CNN 8.2.4 R-FCN R-FCN 有哪些创新点 R-FCN仍然属于two-stage目标检测算法&#xff1a;RPN R-FCN Fully convolutional位置敏感得分图&#xff08;position-sentive score maps&#xff09; our region-based detector is ful…

vs code server for wsl closed unexpectedly

前言&#xff1a; 我的Windows 版本&#xff1a; 10.0.19045.4291 &#xff08;如果你是Win11或者你要使用WSL2请谨慎&#xff09; 之前是可以用的&#xff0c;但安装Vmware&#xff08;并安装了Ubuntu进行了一番实验后&#xff0c;就出现如标题所述问题&#xff09; 问题&a…

【SpringBoot实战篇】获取用户详细信息

1 明确需求 1需要获取用户详细信息 2 接口文档 1基本信息 2请求参数 无 3 响应数据 响应数据类型&#xff1a;application/json 响应参数说明&#xff1a; 响应数据样例 3 思路分析 1用户名在请求头里获取 4 开发 4.1 控制器usercontroller GetMapping("/userInfo")p…

Solidworks 2024安装教程(附免费安装包资源)

鼠标右击软件压缩包&#xff0c;选择“解压到Solidworks.2024”。 打开解压后的文件夹下的“SolidSQUAD”&#xff0c;双击“sw2024_network_serials_licensing”。 点击“是”。 点击“确定”。 复制“SolidWorks_Flexnet_Server”文件夹。 将其粘贴至C盘。 打开复制后的文件夹…