19_SpringBoot拓展注解@SpringBootApplication和@Configuration

news2024/10/3 8:23:52

文章目录

  • Spring Boot拓展注解@SpringBootApplication和@Configuration
    • 0x01_@SpringBootApplication
      • @SpringBootConfiguration
      • @EnableAutoConfiguration
      • @ComponentScan
    • 0x02_@Configuration
      • Full 全模式,Lite 轻量级模式

Spring Boot拓展注解@SpringBootApplication和@Configuration

0x01_@SpringBootApplication

这个注解在分析Spring boot启动原理时,看过源码分析过,在这个注解的源码中,最重要的是其上的几个注解:

image-20221215131921889

如果在项目的启动类中,不用@SpringBootApplication注解,而用上面的3个注解,一样可以启动:

注意:@ComponentScan要指定扫描的包。

package com.bones;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

//@SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.bones")
public class SpringbootannoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootannoApplication.class, args);
    }

}

关于@SpringBootApplication注解里面的3个子注解,下面详细分析一下:

@SpringBootConfiguration

为什么@SpringBootApplication注解里没有包含@Configuration,实际上是在@SpringBootConfiguration里面

@SpringBootConfiguration注解源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {

	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;

}

@SpringBootConfiguration继承自@Configuration,二者功能也一致,标注当前类是配置类, 并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名

只不过@SpringBootConfiguration是springboot的注解,而@Configuration是spring的注解

从上述源码可以看出,@SpringBootConfiguration注解内部有一个核心注解@Configuration,该注解是Spring框架提供的,表示当前类为一个配置类(XML配置文件的注解表现形式),并可以被组件扫描器扫描。由此可见,@SpringBootConfiguration注解的作用与@Configuration注解相同,都是标识一个可以被组件扫描器扫描的配置类,只不过@SpringBootConfiguration是被Spring Boot进行了重新封装命名而已。

@EnableAutoConfiguration

image-20221215133407617

这个注解的作用:

帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot,并创建对应配置类的Bean,并把该Bean实体交给IoC容器进行管理。

@EnableAutoConfiguration的源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	Class<?>[] exclude() default {};

	String[] excludeName() default {};

}

@EnableAutoConfiguration 注解也是一个组合注解。其中:

  • exclude():排除特定的自动配置类,使它们永远不会被应用.
  • excludeName():排除特定的自动配置类名,使它们永远不会被应用.

通常情况下,我们不需要显示使用 @EnableAutoConfiguration 注解。因为在 @SpringBootApplication 注解上面声明了 @EnableAutoConfiguration 注解。


@EnableAutoConfiguration实现的关键在于引入了AutoConfigurationImportSelector,其核心逻辑为selectImports方法,借助AutoConfigurationImportSelector,它可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。

当springboot扫描到@EnableAutoConfiguration注解时则会将spring-boot-autoconfigure.jar/META-INF/spring.factories文件(上面的截图)中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value里的所有xxxConfiguration类加载到IOC容器中。spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:

@ConditionalOnClass : classpath中存在该类时起效

@ConditionalOnMissingClass : classpath中不存在该类时起效

@ConditionalOnBean : DI容器中存在该类型Bean时起效

@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效

@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效

@ConditionalOnExpression : SpEL表达式结果为true时

@ConditionalOnProperty : 参数设置或者值一致时起效

@ConditionalOnResource : 指定的文件存在时起效

@ConditionalOnJndi : 指定的JNDI存在时起效

@ConditionalOnJava : 指定的Java版本存在时起效

@ConditionalOnWebApplication : Web应用环境下起效

@ConditionalOnNotWebApplication : 非Web应用环境下起效

SpringBoot中EnableAutoConfiguration实现的关键在于引入了AutoConfigurationImportSelector,其核心逻辑为selectImports方法,逻辑大致如下:

  1. 从配置文件META-INF/spring.factories加载所有可能用到的自动配置类;

  2. 去重,并将exclude和excludeName属性携带的类排除;

  3. 过滤,将满足条件(@Conditional)的自动配置类返回;

@ComponentScan

这个是 Spring 框架的注解,它用来指定组件扫描路径,如果用这个注解,它的值必须包含整个工程中全部需要扫描的路径。因为它会覆盖 SpringBootApplication 的默认扫描路径,导致其失效。

0x02_@Configuration

这个注解严格来说是spring的注解。

源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

	@AliasFor(annotation = Component.class)
	String value() default "";

	boolean proxyBeanMethods() default true;

}

下面详细说明proxyBeanMethods属性:

首先发现@Configuration注解上打了一个@component注解

spring会扫描所有@component注解的类及其子类(包括@Configuration注解声明的类),认为这些类是bean, 并且把这些bean对应的beanDefinition放到容器中进行管理。BeanDefinition是对bean的描述,里边存有bean的名称,Class等基本信息

在获取到所有的bean defenition之后,Spring会有一些post process执行,其中一个就是ConfigurationClassPostProcessor, 在这里,Spring会遍历所有的bean definition, 如果发现其中有标记了@Configuration注解的,会对这个类进行CGLIB代理,生成一个代理的类,并且把这个类设置到BeanDefenition的Class属性中。当需要拿到这个bean的实例的时候,会从这个class属性中拿到的Class对象进行反射,那么最终反射出来的是代理增强后的类

代理中对方法进行了增强?在哪方面进行了增强?对于@Bean标记的方法,返回的都是一个bean,在增强的方法中,Spring会先去容器中查看一下是否有这个bean的实例了,如果有了的话,就返回已有对象,没有的话就创建一个,然后放到容器中

看一个简单的案例:

package com.bones.config;

import com.bones.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class CommonConfig {
    @Bean
    public User user1(){
        user2();
        return new User(1,"root","ok");
    }
    @Bean
    public User user2(){
        System.out.println("user2被调用");
        return new User(2,"admin","ok");
    }

}

proxyBeanMethods默认为true,表示cglib会为@Configuration生成一个代理类,因此而在user1中调用user2方法时,会通过代理方法从IOC容器中去获取,这样就是单例的。运行的时候,控制台只打印了一次“user2被调用”就证明了这一点

image-20221215135708206

但是如果将proxyBeanMethods设为false,则表示不生成代理,那么user1中调用user2,会再生成一个对象而不是从IOC容器中获取,这样能提高性能,也造成了多例。运行时控制台会打印两次“user2被调用”,如下图所示。

image-20221215135609559

由这一点拓展的知识点:

Full 全模式,Lite 轻量级模式

Full(proxyBeanMethods = true) :proxyBeanMethods参数设置为true时即为:Full 全模式。 该模式下注入容器中的同一个组件无论被取出多少次都是同一个bean实例,即单实例对象,在该模式下SpringBoot每次启动都会判断检查容器中是否存在该组件(找代理,启动慢,单例)
Lite(proxyBeanMethods = false) :proxyBeanMethods参数设置为false时即为:Lite 轻量级模式。该模式下注入容器中的同一个组件无论被取出多少次都是不同的bean实例,即多实例对象,在该模式下SpringBoot每次启动会跳过检查容器中是否存在该组件(不代理,启动快,多例)
什么时候用Full全模式,什么时候用Lite轻量级模式?
当在你的同一个Configuration配置类中,注入到容器中的bean实例之间有依赖关系时,建议使用Full全模式(在上面的例子中,就是存在依赖关系的,user1依赖user2,建议将proxyBeanMethods设置为true,IDEA也是这么提示的)
当在你的同一个Configuration配置类中,注入到容器中的bean实例之间没有依赖关系时,建议使用Lite轻量级模式,以提高springboot的启动速度和性能

proxyBeanMethods 属性默认值是 true, 也就是说该配置类会被代理(CGLIB),在同一个配置文件中调用其它被 @Bean 注解标注的方法获取对象时会直接从 IOC 容器之中获取

proxyBeanMethods设置为 true,那么直接调用方法获取 bean,不会创建新的 bean,而是会走 bean 的生命周期的行为。

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

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

相关文章

计算机网络原理 课后习题(作业)持续更新ing

【1-03 】试从多个方面比较电路交换、报文交换和分组交换的主要优缺点 &#xff08;1&#xff09;电路交换的主要特点: ①电路交换三个阶段&#xff1a;建立连接、通信、释放连接&#xff1b; ②在整个通信过程中&#xff0c;通信的双方自始至终占用着所使用的物理信道。 由…

多线程知识笔记(五)_单例模式

文章目录1、什么是单例模式2、饿汉模式3、懒汉模式1、什么是单例模式 单例模式是一种设计模式。 什么是设计模式呢&#xff1f;设计模式就是一种模板&#xff0c;就像做饭的时候&#xff0c;新手做饭什么调料都是一把放进锅里&#xff0c;有的菜就讲究调料的先后顺序&#xff…

Java web 2022跟学尚硅谷(十一) Vue基础和Axios基础和json基础

Java web 2022跟学尚硅谷十一后端基础 书城Vue在js中定义对象的2种方式方式一方式二简单的Vue代码绑定元素的属性方式一 v-bind:value方式二 :value双向数据绑定 v-model:方式一方式二 :value可以省略&#xff0c;trim去除首尾空格条件渲染 v-if条件渲染 v-else条件渲染 特别注…

[附源码]Python计算机毕业设计高校医务管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

极地土活性层和永久冻土的比较宏基因组学

北极地区有大约87%由低有机碳矿物土壤组成&#xff0c;但对低碳永久冻土&#xff08;PF&#xff09;和活性层&#xff08;AL&#xff09;土壤中微生物活性的了解仍然有限。多种物理和生物因素可能影响碳循环&#xff0c;包括土壤化学、氮等养分的可用性以及现有微生物群落的结构…

论文解析[9] Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

发表时间&#xff1a;2021 论文地址&#xff1a;https://arxiv.org/abs/2103.14030 代码地址&#xff1a;https://github.com/microsoft/Swin-Transformer 文章目录摘要3 方法3.1 总体框架3.2 基于自注意力的移动窗口3.3 结构变形5 结论摘要 这篇论文提出了一个新的ViT叫作Swi…

大数据培训kettle安装部署

kettle安装部署和使用 2.1 kettle安装地址 官网地址 https://community.hitachivantara.com/docs/DOC-1009855 下载地址 https://sourceforge.net/projects/pentaho/files/Data%20Integration/ 2.2 Windows下安装使用 2.2.1 概述 在实际企业开发中&#xff0c;都是在本…

Html 小功能总结二

文章目录一、Html 实现弹窗的实例二、Html 实现流程图三、制作一个简单的菜单功能一、Html 实现弹窗的实例 <!DOCTYPE html> <html> <head><meta charset"utf-8" /><title></title><style type"text/css">body…

C++ Reference: Standard C++ Library reference: Containers: map: map: crbegin

C官网参考链接&#xff1a;https://cplusplus.com/reference/map/map/crbegin/ 公有成员函数 <map> std::map::crbegin const_reverse_iterator crbegin() const noexcept;返回指向反向开始的const_reverse_iterator 返回一个指向容器中最后一个元素的const_reverse_ite…

Nacos 消息通知系统 源码讲解

目录 1. 介绍 2. Nacos 中的生产者 3. Nacos 中的消费者 4. Nacos 中的事件 5. 统一事件通知中心 NotifyCenter 6. 总结 1. 介绍 Nacos 节点内部使用了大量的事件机制进行通信&#xff0c;这样各种操作进行了解耦&#xff0c;提高了性能。 接下来就介绍。 所谓事件机制…

virtualenv系列 (5) · 打通virtualenvwrapper和PyCharm/IntelliJ IDEA的虚拟环境

PyCharm/IntelliJ IDEA已经内置了对virtualenv的支持&#xff0c;当我们为一个项目创建一个新的Python SDK时&#xff0c;就会进入到Add Python Interpreter对话框&#xff0c;选择Virtualenv Environment -> New environment就将创建一套新的virtualenv环境。这里&#xff…

关于长三角某高校能效管理平台应用成效探讨

更多请关注&#xff1a;安科瑞电气网 摘要&#xff1a; 随着现代科学技术的发展&#xff0c;在高校中开始广泛应用智能化技术&#xff0c;改善学生宿舍的用电管理模式&#xff0c;提高宿舍的管理水平&#xff0c;有利于实现高校宿舍用电管理的科学化。本文主要阐述传统高校宿…

D2. Seating Arrangements (hard version)(贪心+排序)

Problem - 1566D2 - Codeforces 这是该问题的困难版本。唯一的区别是&#xff0c;在这个版本中&#xff0c;1≤n≤300。 电影院的座位可以表示为有n行和m列的表格。每行的座位都用1到n的整数编号&#xff0c;从左到右连续编号&#xff1a;在第k行&#xff0c;从m(k-1)1到mk&am…

前端的视角聊聊如何快速入门Python

对于 NodeJs 开发的小伙伴&#xff0c;使用 node-gyp 将 C 模块转换成 NodeJs 的 addon 插件时会依赖 Python 的安装环境&#xff08;针对使用了 nvm 等版本管理工具的情况&#xff09;。对于前端小伙伴来说&#xff0c;Python 本身确实不是一个必须学习的语言&#xff0c;但也…

提前做好网络安全分析,运维真轻松(一)

背景 某汽车总部已部署NetInside流量分析系统&#xff0c;使用流量分析系统提供实时和历史原始流量。汽车配件电子图册系统是某汽车集团的重要业务系统。本次分析重点针对汽车配件电子图册系统进行预见性分析&#xff0c;以供安全取证、性能分析、网络质量监测以及深层网络分析…

SQL基础——聚合与排序

聚合与排序前言思维导图聚合函数示例表3-1![在这里插入图片描述](https://img-blog.csdnimg.cn/9c286053f87a4ae882bece8128bdcab5.png)计算表中数据的行数 COUNT函数示例代码3.1 计算全部数据的行数执行结果计算NULL之外的数据的行数代码示例3.2 计算NULL之外的数据行数执行结…

【DevOps实战系列】第五章:基于Gitlab/Maven/Jenkins/Docker实战案例详解

个人亲自录制全套DevOps系列实战教程 &#xff1a;手把手教你玩转DevOps全栈技术 从创建Jenkins的job开始 1.gitlab设置&#xff1a; 我们从新建一个jenkins任务开始&#xff0c;建一个自由风格项目&#xff0c;我们暂时只让他能拉取git的代码。 路径&#xff1a;从gitlab上新…

【ML笔记】5、支持向量机(SVM)

支持向量机&#xff08;SVM&#xff09;是一个强大的和通用的ML模型&#xff0c;能够执行分类&#xff0c;回归&#xff0c;甚至异常值检测&#xff0c;特别适合于复杂的中小型数据集。 1、线性SVM分类 我们可以看到&#xff0c;这两个类可以很容易地用一条直线(线性可分)分开…

GAN入门知识

GAN入门知识 结构 正式说 GAN 之前我们先说一下判别式模型和生成式模型。 判别器 判别式模型 判别式模型&#xff0c;即 Discriminative Model&#xff0c;又被称为条件概率模型&#xff0c;它估计的是条件概率分布(conditional distribution)&#xff0c; p(class|context) 。…

图书网上商店

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 1