欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 深入探索Spring:Bean管理与Spring Boot自动配置原理

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

2025/4/20 9:01:25 来源:https://blog.csdn.net/2302_81090306/article/details/147339872  浏览:    关键词:深入探索Spring:Bean管理与Spring Boot自动配置原理

目录

  • Spring 原理深入探索
    • 1. Bean 的作用域和生命周期
      • 1.1 Bean 的作用域
      • 1.2 Bean 的生命周期
    • 2. Spring Boot 自动配置流程
    • 3.总结

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实体类:

public class Dog {private  String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}

创建一个DogCompoent类(交给Spring进行管理):

@Component
public class DogCompoent {@Beanpublic Dog dog(){return new Dog();}
//    单例@Beanpublic Dog singleDog(){return new Dog();}
//    多例@Bean@Scope("prototype")public Dog prototypeDog(){return new Dog();}
//request@Bean@RequestScopepublic Dog requestDog(){return new Dog();}//session@Bean@SessionScopepublic Dog sessionDog(){return new Dog();}//application@Bean@ApplicationScopepublic Dog applicationDog(){return new Dog();}
}

定义一个controller类:

@RestController
@RequestMapping("/dog")
public class DogController {@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")public String singleton(){Dog contextDog = context.getBean("singleDog", Dog.class);return "contextDog"+contextDog+",resource"+singleDog;}@RequestMapping("/prototype")public String prototype(){Dog contextDog = context.getBean("prototypeDog", Dog.class);return "contextDog"+contextDog+",resource"+prototypeDog;}@RequestMapping("/request")public String  request(){Dog contextDog = context.getBean("requestDog", Dog.class);return "contextDog"+contextDog+",resource"+ requestDog;}@RequestMapping("/session")public String session(){Dog contextDog = context.getBean("sessionDog", Dog.class);return "contextDog"+contextDog+",resource"+ sessionDog;}@RequestMapping("/application")public String application(){Dog contextDog = context.getBean("applicationDog", Dog.class);return "contextDog"+contextDog+",resource"+ applicationDog;}
}

启动类:

@SpringBootApplication
public class SpringPrincipleApplication {public static void main(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的生命周期从创建到销毁。

代码:

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class BeanLifeComponent implements BeanNameAware {
//
//    @Autowiredprivate DogCompoent dogCompoent;//1. 实例化public BeanLifeComponent() {System.out.println("执行构造方法....");}//    2.属性赋值(seter方法注入)
@Autowiredpublic void setDogCompoent(DogCompoent dogCompoent) {this.dogCompoent = dogCompoent;System.out.println("执行属性赋值");
}
//获取Bean的名称@Overridepublic void setBeanName(String name) {System.out.println("执行BeanNameAware,beanName:"+name);}
//    初始化方法@PostConstructpublic void init(){System.out.println("初始化方法...");}
//    4.使用Beanpublic void use(){System.out.println("使用Bean,执行use 方法");}//    5.销毁Bean@PreDestroypublic void destroy(){System.out.println("销毁bean");}
}

启动项目:
在这里插入图片描述
进行测试:

	@Testvoid testBean(){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)简化了配置过程,以下是其核心流程:

数据准备

在这里插入图片描述

import org.springframework.context.annotation.Configuration;
//第三方
@Configuration
public class Sliqverconfig {public void study(){System.out.println("Sliqverconfig study... ");}
}

获取Sliqverconfig这个Bean
写测试用例:

	@AutowiredApplicationContext context;@Testvoid testBean(){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")
@SpringBootApplication
public class SpringPrincipleApplication {public static void main(String[] args) {
SpringApplication.run(SpringPrincipleApplication.class, args);}
}

再进行测试:
在这里插入图片描述
获取成功.

2. @Import

导入类

@Import(Sliqverconfig.class)
@SpringBootApplication
public class SpringPrincipleApplication {public static void main(String[] args) {
SpringApplication.run(SpringPrincipleApplication.class, args);}
}

再进行测试:
在这里插入图片描述
获取成功.


导⼊ ImportSelector 接口实现类


public class MySelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.config.Sliqverconfig"};}
}

启动类:

@Import(MyRegistrar.class)
@SpringBootApplication
public class SpringPrincipleApplication {public static void main(String[] args) {
SpringApplication.run(SpringPrincipleApplication.class, args);}
}

再进行测试:
在这里插入图片描述
获取成功.

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

第三⽅依赖提供注解.

import org.springframework.context.annotation.Import;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//注解
//类
@Target(ElementType.TYPE)
//生命周期
@Retention(RetentionPolicy.RUNTIME)
@Import(MySelector.class)//指定要导入的类
public @interface EnableSliqversConfig {}

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

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

//通过第三方注解 @EnableSliqversConfig
@EnableSliqversConfig
@SpringBootApplication
public class SpringPrincipleApplication {public static void main(String[] args) {
SpringApplication.run(SpringPrincipleApplication.class, args);}
}

再进行测试:
在这里插入图片描述
获取成功.


Spring boot 配置流程如下:
在这里插入图片描述

3.总结

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词