深入探索Spring:Bean管理与Spring Boot自动配置原理

深入探索Spring:Bean管理与Spring Boot自动配置原理

目录

Spring 原理深入探索

1. Bean 的作用域和生命周期

1.1 Bean 的作用域

在Spring中,Bean的作用域(Scope)决定了Bean的实例化方式以及其生命周期。以下是Spring中常见的Bean作用域:

作用域说明
singleton每个Spring IoC容器内同名称的bean只有⼀个实例(单例)(默认 )
prototype每次使用该bean时会创建新的实例(非单例)
request每个HTTP 请求生命周期内, 创建新的实例
session每个HTTP Session生命周期内, 创建新的实例
application每个ServletContext生命周期内, 创建新的实例
websocket每个WebSocket生命周期内, 创建新的实例

我们直接上代码 后面根据运行结果观察Bean的作用域。

创建一个Dog实体类:
publicclassDog{privateString name;publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}}

创建一个DogCompoent类(交给Spring进行管理):
@ComponentpublicclassDogCompoent{@BeanpublicDogdog(){returnnewDog();}// 单例@BeanpublicDogsingleDog(){returnnewDog();}// 多例@Bean@Scope("prototype")publicDogprototypeDog(){returnnewDog();}//request@Bean@RequestScopepublicDogrequestDog(){returnnewDog();}//session@Bean@SessionScopepublicDogsessionDog(){returnnewDog();}//application@Bean@ApplicationScopepublicDogapplicationDog(){returnnewDog();}}
定义一个controller类:
@RestController@RequestMapping("/dog")publicclassDogController{@AutowiredApplicationContext context;// 单例作用域@Resource(name ="singleDog")Dog singleDog;// 多例作用域(原型)@Resource(name="prototypeDog")Dog prototypeDog;//@Resource(name ="requestDog")Dog requestDog;//@Resource(name ="sessionDog")Dog sessionDog;//@Resource(name ="applicationDog")Dog applicationDog;@RequestMapping("/singleton")publicStringsingleton(){Dog contextDog = context.getBean("singleDog",Dog.class);return"contextDog"+contextDog+",resource"+singleDog;}@RequestMapping("/prototype")publicStringprototype(){Dog contextDog = context.getBean("prototypeDog",Dog.class);return"contextDog"+contextDog+",resource"+prototypeDog;}@RequestMapping("/request")publicStringrequest(){Dog contextDog = context.getBean("requestDog",Dog.class);return"contextDog"+contextDog+",resource"+ requestDog;}@RequestMapping("/session")publicStringsession(){Dog contextDog = context.getBean("sessionDog",Dog.class);return"contextDog"+contextDog+",resource"+ sessionDog;}@RequestMapping("/application")publicStringapplication(){Dog contextDog = context.getBean("applicationDog",Dog.class);return"contextDog"+contextDog+",resource"+ applicationDog;}}
启动类:
@SpringBootApplicationpublicclassSpringPrincipleApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SpringPrincipleApplication.class, args);}}

启动项目: 测试不同作用域的Bean取到的对象是否一样:

  • Singleton(单例)
    • Spring默认的作用域,所有客户端共享同一个Bean实例。
    • 适用于无状态Bean。

单例作用域的Bean:http://127.0.0.1:8080:/dog/singleton

在这里插入图片描述


多次访问, 得到的都是同⼀个对象, 并且 @Autowired 和applicationContext.getBean()也是同⼀个对象。

在这里插入图片描述

  • Prototype(原型)
    • 每次注入或获取Bean时,都会创建一个新的实例。
    • 适用于有状态Bean。

原型作用域的Bean:http://127.0.0.1:8080:/dog/prototype

在这里插入图片描述


观察ContextDog, 每次获取的对象都不⼀样(注入的对象在Spring容器启动时, 就已经注入了, 所以多次请求也不会发生变化)

在这里插入图片描述

  • Request(请求范围)
    • 每个HTTP请求创建一个新的Bean实例。
    • 适用于Web应用中的请求相关数据。
      request作用域的Bean:http://127.0.0.1:8080:/dog/request
在这里插入图片描述


在⼀次请求中, @Autowired 和 applicationContext.getBean() 也是同⼀个对象.但是每次请求, 都会重新创建对象.

在这里插入图片描述

  • Session(会话范围)
    • 每个HTTP会话创建一个新的Bean实例。
    • 适用于用户会话相关数据。

session作用域的Bean:http://127.0.0.1:8080:/dog/session

在这里插入图片描述


在这里插入图片描述


在一个session当中,多次请求,获取的对象都是同一个。
但是我们换一个浏览器访问会重新创建对象(另外一个session)

  • Application(应用范围)
    • 每个ServletContext创建一个Bean实例。

session作用域的Bean:http://127.0.0.1:8080:/dog/application

在这里插入图片描述
在⼀个应用中, 多次访问都是同一个对象.
Application scope就是对于整个web容器来说, bean的作⽤域是ServletContext级别的. 这个和
singleton有点类似,区别在于: Application scope是ServletContext的单例, singleton是⼀个
ApplicationContext的单例. 在⼀个web容器中ApplicationContext可以有多个。

1.2 Bean 的生命周期

Bean的生命周期从创建到销毁,Spring对其进行了详细的管理:

  1. Bean的创建
    • 通过构造器或工厂方法创建Bean实例。
  2. 依赖注入
    • 根据配置注入Bean的依赖项。
  3. 初始化回调
    • 调用Bean的初始化方法(如@PostConstruct注解标注的方法)。
    • Spring的InitializingBean接口或自定义初始化方法。
  4. Bean可用
    • Bean已经准备就绪,可以被应用程序使用。
  5. 销毁回调
    • 当应用上下文关闭时,调用Bean的销毁方法。
    • @PreDestroy注解标注的方法,或DisposableBean接口。

创建一个BeanLifeComponent类继承BeanNameAware来说明Bean的生命周期从创建到销毁。

代码:

importjakarta.annotation.PostConstruct;importjakarta.annotation.PreDestroy;importorg.springframework.beans.factory.BeanNameAware;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;@ComponentpublicclassBeanLifeComponentimplementsBeanNameAware{//// @AutowiredprivateDogCompoent dogCompoent;//1. 实例化publicBeanLifeComponent(){System.out.println("执行构造方法....");}// 2.属性赋值(seter方法注入)@AutowiredpublicvoidsetDogCompoent(DogCompoent dogCompoent){this.dogCompoent = dogCompoent;System.out.println("执行属性赋值");}//获取Bean的名称@OverridepublicvoidsetBeanName(String name){System.out.println("执行BeanNameAware,beanName:"+name);}// 初始化方法@PostConstructpublicvoidinit(){System.out.println("初始化方法...");}// 4.使用Beanpublicvoiduse(){System.out.println("使用Bean,执行use 方法");}// 5.销毁Bean@PreDestroypublicvoiddestroy(){System.out.println("销毁bean");}}

启动项目:

在这里插入图片描述


进行测试:

@TestvoidtestBean(){BeanLifeComponent bean = context.getBean(BeanLifeComponent.class); bean.use();}
在这里插入图片描述

可以看到使用Bean成功了。
流程:

在这里插入图片描述

2. Spring Boot 自动配置流程

SpringBoot的自动配置就是当Spring容器启动后, ⼀些配置类, bean对象等就自动存入到了IoC容器中,不需要我们手动去声明, 从而简化了开发, 省去了繁琐的配置操作。
SpringBoot自动配置, 就是指SpringBoot是如何将依赖jar包中的配置类以及Bean加载到Spring IoC容器中的Spring Boot通过自动配置(Auto-Configuration)简化了配置过程,以下是其核心流程:
数据准备
在这里插入图片描述
importorg.springframework.context.annotation.Configuration;//第三方@ConfigurationpublicclassSliqverconfig{publicvoidstudy(){System.out.println("Sliqverconfig study... ");}}

获取Sliqverconfig这个Bean
写测试用例:
@AutowiredApplicationContext context;@TestvoidtestBean(){Sliqverconfig bean = context.getBean(Sliqverconfig.class);System.out.println(bean);}
在这里插入图片描述


可以看到测试报错,那这个是什么原因呢?

原因分析

Spring通过五⼤注解和 @Bean 注解可以帮助我们把Bean加载到SpringIoC容器中, 以上有个前提就是这些注解类需要和SpringBoot启动类在同⼀个目录下 ( @SpringBootApplication 标注的类 就是SpringBoot项目的启动类。

在这里插入图片描述


可以看到这个Sliqverconfig类并不和启动类在同一个包下面。
这个Sliqverconfig类相当于第三方包,那我们怎么样把这个包,交给Spring管理这些Bean呢?

解决方案

我们需要指定路径或者引入的文件, 告诉Spring, 让Spring进行扫描到.
常见的解决方法有两种:

1. @ComponentScan 组件扫描

@ComponentScan(basePackages ="com.config")@SpringBootApplicationpublicclassSpringPrincipleApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SpringPrincipleApplication.class, args);}}

再进行测试:

在这里插入图片描述


获取成功.

2. @Import

导入类
@Import(Sliqverconfig.class)@SpringBootApplicationpublicclassSpringPrincipleApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SpringPrincipleApplication.class, args);}}

再进行测试:

在这里插入图片描述


获取成功.


导⼊ ImportSelector 接口实现类
publicclassMySelectorimplementsImportSelector{@OverridepublicString[]selectImports(AnnotationMetadata importingClassMetadata){returnnewString[]{"com.config.Sliqverconfig"};}}

启动类:

@Import(MyRegistrar.class)@SpringBootApplicationpublicclassSpringPrincipleApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SpringPrincipleApplication.class, args);}}

再进行测试:

在这里插入图片描述


获取成功.

问题:
但是他们都有⼀个明显的问题, 就是使用者需要知道第三方依赖中有哪些Bean对象或配置类. 如果漏掉其中⼀些Bean, 很可能导致我们的项目出现大的事故.这对程序员来说非常不友好.
依赖中有哪些Bean, 使用时候需要配置哪些bean, 第三方依赖最清楚, 那能否由第三方依赖来做这件事呢?
比较常见的方法就是第三方依赖给我们提供⼀个注解, 这个注解⼀般都以@EnableXxxx开头的注解,注解中封装的就是 @Import 注解.

第三⽅依赖提供注解.
importorg.springframework.context.annotation.Import;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;//注解//类@Target(ElementType.TYPE)//生命周期@Retention(RetentionPolicy.RUNTIME)@Import(MySelector.class)//指定要导入的类public@interfaceEnableSliqversConfig{}

注解中封装 @Import 注解, 导入MySelector.class

启动类:
直接使用第三方提供的注解:

//通过第三方注解 @EnableSliqversConfig@EnableSliqversConfig@SpringBootApplicationpublicclassSpringPrincipleApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SpringPrincipleApplication.class, args);}}

再进行测试:

在这里插入图片描述


获取成功.


Spring boot 配置流程如下:

在这里插入图片描述

3.总结

Spring的Bean管理和生命周期机制是其核心功能,而Spring Boot的自动配置流程则大大简化了配置工作,帮助开发者快速构建应用。

Read more

安装 启动 使用 Neo4j的超详细教程

安装 启动 使用 Neo4j的超详细教程

最近在做一个基于知识图谱的智能生成项目。需要用到Neo4j图数据库。写这篇文章记录一下Neo4j的安装及其使用。 一.Neo4j的安装 1.首先安装JDK,配环境变量。(参照网上教程,很多) Neo4j是基于Java的图形数据库,运行Neo4j需要启动JVM进程,因此必须安装JAVA SE的JDK。从Oracle官方网站下载 Java SE JDK。我使用的版本是JDK1.8 2.官网上安装neo4j。 官方网址:https://neo4j.com/deployment-center/  在官网上下载对应版本。Neo4j应用程序有如下主要的目录结构: bin目录:用于存储Neo4j的可执行程序; conf目录:用于控制Neo4j启动的配置文件; data目录:用于存储核心数据库文件; plugins目录:用于存储Neo4j的插件; 3.配置环境变量 创建主目录环境变量NEO4J_HOME,并把主目录设置为变量值。复制具体的neo4j文件地址作为变量值。 配置文档存储在conf目录下,Neo4j通过配置文件neo4j.conf控制服务器的工作。默认情况下,不需

企业微信群机器人Webhook配置全攻略:从创建到发送消息的完整流程

企业微信群机器人Webhook配置全攻略:从创建到发送消息的完整流程 在数字化办公日益普及的今天,企业微信作为国内领先的企业级通讯工具,其群机器人功能为团队协作带来了极大的便利。本文将手把手教你如何从零开始配置企业微信群机器人Webhook,实现自动化消息推送,提升团队沟通效率。 1. 准备工作与环境配置 在开始创建机器人之前,需要确保满足以下基本条件: * 企业微信账号:拥有有效的企业微信管理员或成员账号 * 群聊条件:至少包含3名成员的群聊(这是创建机器人的最低人数要求) * 网络环境:能够正常访问企业微信服务器 提示:如果是企业管理员,建议先在"企业微信管理后台"确认机器人功能是否已对企业开放。某些企业可能出于安全考虑会限制此功能。 2. 创建群机器人 2.1 添加机器人到群聊 1. 打开企业微信客户端,进入目标群聊 2. 点击右上角的群菜单按钮(通常显示为"..."或"⋮") 3. 选择"添加群机器人"选项 4.

Flowise物联网融合:与智能家居设备联动的应用设想

Flowise物联网融合:与智能家居设备联动的应用设想 1. Flowise:让AI工作流变得像搭积木一样简单 Flowise 是一个真正把“AI平民化”落地的工具。它不像传统开发那样需要写几十行 LangChain 代码、配置向量库、调试提示词模板,而是把所有这些能力打包成一个个可拖拽的节点——就像小时候玩乐高,你不需要懂塑料怎么合成,只要知道哪块该拼在哪,就能搭出一座城堡。 它诞生于2023年,短短一年就收获了45.6k GitHub Stars,MIT协议开源,意味着你可以放心把它用在公司内部系统里,甚至嵌入到客户交付的产品中,完全不用担心授权问题。最打动人的不是它的技术多炫酷,而是它真的“不挑人”:产品经理能搭出知识库问答机器人,运营同学能配出自动抓取竞品文案的Agent,连刚学Python两周的实习生,也能在5分钟内跑通一个本地大模型的RAG流程。 它的核心逻辑很朴素:把LangChain里那些抽象概念——比如LLM调用、文档切分、向量检索、工具调用——变成画布上看得见、摸得着的方块。你拖一个“Ollama LLM”节点,再拖一个“Chroma Vector

OpenClaw配置Bot接入飞书机器人+Kimi2.5

OpenClaw配置Bot接入飞书机器人+Kimi2.5

上一篇文章写了Ubuntu_24.04下安装OpenClaw的过程,这篇文档记录一下接入飞书机器+Kimi2.5。 准备工作 飞书 创建飞书机器人 访问飞书开放平台:https://open.feishu.cn/app,点击创建应用: 填写应用名称和描述后就直接创建: 复制App ID 和 App Secret 创建成功后,在“凭证与基础信息”中找到 App ID 和 App Secret,把这2个信息复制记录下来,后面需要配置到openclaw中 配置权限 点击【权限管理】→【开通权限】 或使用【批量导入/导出权限】,选择导入,输入以下内容,如下图 点击【下一步,确认新增权限】即可开通所需要的权限。 配置事件与回调 说明:这一步的配置需要先讲AppId和AppSecret配置到openclaw成功之后再设置订阅方式,