Spring注解-1-SpringBoot是如何处理注解的

2023-05-16

本文基于Spring 5.2.7

这是个很大的话题,但是是个非常实在的话题,注解天天用,处处用,请问你知道他是怎么起作用的吗?
如果你使用了注解,那么一定有代码在什么地方检索这个注解,并为这个注解的语义写了对应的逻辑。但是注解本身是没有任何行为的,他只是一个标记而已。所以注解是惰性的,看到注解时并没有行为,你需要找到注解对应的行为才能理解注解实际的作用。
但是要找到一个注解对应的行为很难,因为很多注解都是些三方库提供的,要想找到每个注解对应的行为有如大海捞针,能搞清楚这个知识点很难。

一、SpringBoot启动

SpringBoot要解析哪些注解在代码中已经写死了,所有注解的解析都是按照既定的顺序在执行,如@Configuration,@Import,这些都会在启动过程中解析,所以一切的起点是启动类上,但是,我们会看到启动类上往往是一个汇总的注解,如@EnableTransactionManagement,然后这个类上面会引入其他注解,那Spring是怎么解析到他引入的注解的呢?

原理就是Spring在扫描注解是一种递归的方式,比如在处理@Import注解时,就会递归处理:
org.springframework.context.annotation.ConfigurationClassParser#collectImports(...)

private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
		throws IOException {

	if (visited.add(sourceClass)) {
		for (SourceClass annotation : sourceClass.getAnnotations()) {
			String annName = annotation.getMetadata().getClassName();
			if (!annName.equals(Import.class.getName())) {
				collectImports(annotation, imports, visited);
			}
		}
		imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
	}
}

这是Spring在启动解析配置时,递归解析注解,这里的sourceClass就是启动类,然后递归检查启动类上的@Import注解,所以才能检查到注解上的注解。

一般而言,spring会扫描所有的类,而且会扫描这些类上面的注解,Spring自身提供了很多注解,你写了Spring提供的注解,他就会扫描到,进而执行响应的动作。

你可以在启动类上写很多注解,必须要写的注解是org.springframework.boot.autoconfigure.SpringBootApplication
我们已经写了main()方法,SpringBoot已经自主启动运行,此时他会回过头来扫描启动类上的注解并解析,其实SpringBootApplication这个注解本身并没有语义,他是一个复合注解,用于引入其他的注解,这就要求Spring在扫描注解时能够递归扫描,实际上Spring就是这么做的。在判断一个bean上是否有某个注解时,Spring都是递归解析注解的。或者说所有的复合注解都是没有语义的,有语义的是复合注解上的单个注解。​​​​​​​

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

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};

	/**
	 * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
	 * for a type-safe alternative to String-based package names.
	 * <p>
	 * <strong>Note:</strong> this setting is an alias for
	 * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
	 * scanning or Spring Data {@link Repository} scanning. For those you should add
	 * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
	 * {@code @Enable...Repositories} annotations.
	 * @return base packages to scan
	 * @since 1.3.0
	 */
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};

	/**
	 * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
	 * scan for annotated components. The package of each class specified will be scanned.
	 * <p>
	 * Consider creating a special no-op marker class or interface in each package that
	 * serves no purpose other than being referenced by this attribute.
	 * <p>
	 * <strong>Note:</strong> this setting is an alias for
	 * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
	 * scanning or Spring Data {@link Repository} scanning. For those you should add
	 * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
	 * {@code @Enable...Repositories} annotations.
	 * @return base packages to scan
	 * @since 1.3.0
	 */
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};

	/**
	 * Specify whether {@link Bean @Bean} methods should get proxied in order to enforce
	 * bean lifecycle behavior, e.g. to return shared singleton bean instances even in
	 * case of direct {@code @Bean} method calls in user code. This feature requires
	 * method interception, implemented through a runtime-generated CGLIB subclass which
	 * comes with limitations such as the configuration class and its methods not being
	 * allowed to declare {@code final}.
	 * <p>
	 * The default is {@code true}, allowing for 'inter-bean references' within the
	 * configuration class as well as for external calls to this configuration's
	 * {@code @Bean} methods, e.g. from another configuration class. If this is not needed
	 * since each of this particular configuration's {@code @Bean} methods is
	 * self-contained and designed as a plain factory method for container use, switch
	 * this flag to {@code false} in order to avoid CGLIB subclass processing.
	 * <p>
	 * Turning off bean method interception effectively processes {@code @Bean} methods
	 * individually like when declared on non-{@code @Configuration} classes, a.k.a.
	 * "@Bean Lite Mode" (see {@link Bean @Bean's javadoc}). It is therefore behaviorally
	 * equivalent to removing the {@code @Configuration} stereotype.
	 * @since 2.2
	 * @return whether to proxy {@code @Bean} methods
	 */
	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;

}

SpringBoot的run()方法里已经执行了很多事情,他里面就会扫描所有bean,并处理相关注解。启动类上面的注解此时也会被处理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring注解-1-SpringBoot是如何处理注解的 的相关文章

随机推荐

  • Ubuntu修改密码及密码复杂度策略设置方法

    版本查看 cat span class token operator span etc span class token operator span issue cat span class token operator span proc
  • 2022小米红米手机最新最全MIUI刷机教程内测版到稳定版 不清除数据(线刷、卡刷)

    文章目录 方法1 xff1a 解锁 线刷手机解锁解锁软件接入电脑刷机工具下载下载刷机包线刷 方法2 xff1a 小米助手卡刷包下载小米助手PC客户端打开手机USB调试模式连接小米助手卡刷miui卡刷包下载 起因是因为意外升级了一版内测版mi
  • TreeSet录入重复的元素及保证录入&输出顺序一致的Java实现

    Java萌新在学习路上遇到的一个扯dan的问题解法 知识点 Set TreeSet TreeSet自然排序 TreeSet比较器排序 Comparator 原题目 请编写main 方法 xff0c 按以下要求顺序 循环接收控制台录入的字符串
  • SpringBoot无法访问static文件夹 404问题

    使用spring boot 配置好后端 导入前端页面到resources 61 gt static 文件夹后 无法访问 但此时进入调试模式 访问controller的路径时 发现后台已经传送出去json数据 64 RequestMappin
  • Ubuntu虚拟机反复在登录界面循环问题

    登录Ubuntu的时候发现登录界面不对劲 xff0c 之前从来没有看到过 而且无法登录 xff0c 反复在登录界面循环 百度 xff0c 说原因有两个 xff1a 1 环境变量修改有问题 xff1b 2 显卡驱动有问题 xff1b 均尝试数
  • pycharm设置笔记

    目录 区分级别显示高亮日志 区分级别显示高亮日志 效果 设置log highlighting里填入 s E RROR s 即可 s E RROR s
  • Ubuntu设置开机自启动

    文章目录 前言一 基本概念二 操作步骤1 终端输入2 设置路径 总结 前言 本文介绍如何在Ubuntu设置开机自启动 一 基本概念 除了系统上配置的默认启动应用程序之外 xff0c gnome session properties 程序使用
  • uniapp 发布网站遇到的问题(跨域,nginx代理失败,index无法打开,手机端无法访问等)

    跨域 如果开发的应用直接是作为手机APP是不存在跨域问题的 xff0c 但是如果是网站形式就要考虑这个问题了 分为两点 xff1a 1 调试时 可通过设置maintest 2 发布后 可通过Nginx配置文件设置代理 nginx代理失败 1
  • 怎么在linux上安装vnc

    1 首先检查是否安装了VNC服务 输入命令 xff1a rpm qa grep vnc 2 安装VNC xff0c 首次执行vncserver需要设置密码 xff0c 可以创建多个桌面 xff0c 执行多次vncserver命令即可 roo
  • VNC修改端口号

    1 vnc的默认端口是自己配置的 xff0c 想要修改vncserver的配置 xff0c 需要先找配置文件路径 root 64 node04 which vncserver usr bin vncserver 2 通过查找以前配置的端口
  • onNewIntent使用遇到的坑

    onCreate是用来创建一个Activity也就是创建一个窗体 xff0c 但一个Activty处于任务栈的顶端 xff0c 若再次调用startActivity去创建它 xff0c 则不会再次创建 若你想利用已有的Acivity去处理别
  • CentOS7使用firewall-cmd打开关闭防火墙与端口

    一 centos7版本对防火墙进行加强 不再使用原来的iptables 启用firewalld 1 firewalld的基本使用 启动 xff1a systemctl start firewalld 查状态 xff1a systemctl
  • 算法数学基础-排列组合(题目取自牛客网)

    基础理论 xff1a 排列 有限集的子集按某种条件的序化法排成列 排成一圈 不许重复或许重复等 从n个不同元素中每次取出m xff08 1 m n xff09 个不同元素 xff0c 排成一列 xff0c 称为从n个元素中取出m个元素的无重
  • 关于对Spring框架的详解

    Spring框架 基本概念Spring的形成主要模块三层架构Spring的优点对于Spring 框架中都用到设计模式 xff1a 基本概念 Spring框架是由于软件开发的复杂性而创建的 Spring使用的是基本的JavaBean来完成以前
  • vs2015 提示严重性代码说明项目文件行禁止显示状态 错误C4996 'scanf': This function or variable may be unsafe.

    在 vs2015 中使用scanf时总是提示 unsafe 报出错误 xff0c 解决办法是在已经建立的项目中 xff0c 以后可能需要经常进行再不同的项目进行这项操作 xff1a 项目 gt 属性 gt c c 43 43 gt 常规 g
  • base7. ThreadPool线程池类——生产者与消费者模型

    ThreadPool类图 数据成员 xff1a MutexLock mutex xff1a 一个MutexLock类型的互斥变量mutex Condition cond xff1a 一个Condition类型的条件变量cond string
  • Ubuntu下anaconda中PyCharm遇到的环境问题

    Table of Contents 运行找不到包文件 可以run xff0c 不能debug 运行找不到包文件 解救办法 xff1a 将包的路径添加到interpreter中 可以run xff0c 不能debug 去掉setting中py
  • origin画图——同一图中多组数据

    origin画图 同一图中多组数据 xff08 2维 xff09 导入数据分别确定X Y轴列数据 xff08 选中列 set as X Y xff0c 全选数据 xff0c 点击下方绘图图标
  • pacman用法

    Pacman 是archlinux 下的包管理软件 它将一个简单的二进制包格式和易用的构建系统结合了起来 不管软件包是来自官方的 Arch 库还是用户自己创建 xff0c Pacman 都能方便得管理 pacman Sy abc 和源同步后
  • Spring注解-1-SpringBoot是如何处理注解的

    本文基于Spring 5 2 7 这是个很大的话题 xff0c 但是是个非常实在的话题 xff0c 注解天天用 xff0c 处处用 xff0c 请问你知道他是怎么起作用的吗 xff1f 如果你使用了注解 xff0c 那么一定有代码在什么地方