一篇文章全知全能SpringBoot Bean的生命周期

news2024/10/6 4:13:31

系列文章:https://gamwatcher.blog.csdn.net/article/details/124603278

这篇文章也是计划了蛮久的了,一直没写,正所谓大道行思,取则行远,总结也是学习的一种方式。

🙈记得看目录哦

1、关于spring

1.1 什么是spring

Spring 是一个容器, 包含并且管理应用对象的生命周期。spring主要包括三大部分

Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。

Core 核心模块:提供了 Spring 框架的基本组成部分,主要是 IoC 和 DI 功能。

Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。

1.2 spring和springboot

springboot 看名字也能看出来,spring的启动器,我们看下springboot到底解决了哪些问题

  • 自动配置,还记得在使用spring的时候被xml支配的恐惧吗? 一个又一个的xml不会配置,springboot将一些配置进行缺省,自动配置

  • 部署简单,内嵌式 web 服务器(Tomcat\jetty)等

  • 第三方集成方便,很多插件都提供了starter,直接使用,缺省配置

2、什么是bean

In Spring, the objects that form the backbone of your application and that are managed by the Spring
IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container.

Spring bean是Spring框架在运行时管理的对象,Bean是一个由Spring IoC容器实例化、组装和管理的对象。

3、bean的生命周期

spring的框架发展了好多年,代码实在太复杂了,我们自己做个IOC容器,或者说实现一个spring

3.1 实现步骤

  1. 创建一个factory,用来管理bean,这里假设用map 做缓存

  1. 容器管理bean,在容器启动的时候创建bean的定义,等待复制

  1. 创建单例的bean,

  1. 反射注入,根据构造函数进行注入对应的bean

3.2 实现过程中的问题

  1. bean的定义来源问题,可能来自xml,也可能来自注解

这个就是常规来说的ClassPathXmlApplicationContext(对应xml),FileSystemXmlApplicationContext,AnnotationConfigApplicationContext

  1. 怎么定义BeanDefinition

BeanDefinition中的常用属性

beanClass:表示Bean类型,未加载类的时候存放Bean的名字,加载类后存放Bean的class信息。

scope:表示Bean的作用域,一般值为单例或者原型。

lazyInit:表示Bean是否是懒加载。

initMethodName:Bean初始化需要执行的方法。

destroyMethodName:Bean销毁时要执行的方法。

factoryBeanName:创建当前Bean的工厂。

  1. 怎么读取BeanDefinition

AnnotatedBeanDefinitionReader:解析类上的注解,包含某些注解的时候(如:@Bean、@Component)会成为Bean。

XmlBeanDefinitionReader:可以解析xml文件中的标签。

ClassPathBeanDefinitionScanner:扫描包路径的读取器。

  1. 怎么创建bean

常规的对象创建是直接调用构造函数,然后调用对象的set函数设置属性,这一步要实现自动化

4、正儿八经聊聊spring

4.1、常见图

4.2 个人理解

上面的图画的挺好的很多细节,说实在话开始的时候我只是觉得烦,因为找不到纲领

❤️从三点进行分解

1、bean的实例化和销毁

2、容器的操作,前置,后置处理

3、依赖的解决

4.3 bean 的实例化

bean的实例化无外乎从beanDefinition中进行创建,这部分的源码可以参考AbstractAutowireCapableBeanFactory

4.4 bean的前后置处理

都知道可以在bean引用环境变量@Value,这个值在实例化的时候是怎么设置进去的? 这就是bean的后置处理

ConfigurationClassPostProcessor是spring内置的bean工厂处理器,在进行refresh的时候会被调用,实现对配置类的解析也即对我们注解的

bean进行扫描处理为bd放到缓存beanDefinitionMap中,用于后续进行实例化。

4.5 依赖的解决

正常的依赖解决直接通过赋值就可以,但是Spring的重点是循环依赖,也就是A 引用B,B引用A

循环依赖的问题 在spring中解决主要是通过三级缓存进行解决,这三个缓存其实本质上是三个Map集合。

单例对象的缓存:key存储bean名称,value存储Bean对象【一级缓存】,日常获取bean的位置

早期单例对象的缓存:key存储bean名称,value存储早期的Bean对象【二级缓存】,还没进行属性注入,由三级缓存放入

单例工厂缓存:key存储bean名称,value存储该Bean对应的ObjectFactory对象【三级缓存】

Spring的bean在实例化的过程中不需要全部初始化完成,则直接将对象放入缓存

举个例子:

A,B相互依赖,在实例化A的过程中,发现有依赖B,缓存中不存在,则直接将A放入缓存,

继续实例化B,发现依赖A,则从缓存中取出A,给B赋值,初始化完成后放入缓存,解决了循环依赖的问题

5、Spring中bean 相关的

5.1 bean 相关的类注解

@Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。

@Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。

@Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。

@Controller : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。

@Configuration:主要用于配置,配合@Bean使用

5.2 @Component 和 @Bean 的区别

@Bean注解作用于方法。将方法返回的对象加入到容器中,一般在配置类中使用

5.3 bean的注入

Spring 内置的 @Autowired 以及 JDK 内置的 @Resource 和 @Inject 都可以用于注入 Bean。

@Autowired 默认的注入方式为byType(根据类型进行匹配),可以通过 @Qualifier 注解来显示指定名称

@Resource默认注入方式为 byName(根据名称进行匹配),可以通过 name 属性来显示指定名称

@Inject和@Name一起使用

当一个接口存在多个实现类的情况下,@Autowired 和@Resource都需要通过名称才能正确匹配到对应的 Bean。

@Import注解注入bean,一般在写starter情况下,拉入相关的配置

@Import({XXConfig.class})
public class SpringConfig4 {
}

5.4 bean的注入方式

  • 属性注入,通过setXXX( )方法注入bean的属性值或依赖对象

public class UserServiceImpl implents UserService{
     private UserDao userDao;
     
     @Autowire
     public serUserDao(UserDao userDao){
         this.userDao = userDao;
     }
 }
  • 构造函数注入

public class UserServiceImpl implents UserService{
    private UserDao userDao;
    
    
    public UserServiceImpl(@Autowire UserDao userDao){
        this.userDao = userDao;
    }
}

5.5 bean 作用域

Spring为你的bean提供了几个作用域,@Scope("prototype")

框架的核心有两个:

单例 - 单个实例,bean的默认作用域是单例

原型 - 多个实例,prototype

Spring专门用于Web应用程序的bean作用域:

请求 @RequestScope

会话 @SessionScope

全局会话

应用级别 @ApplicationScope

5.6 bean的回调方法

实现InitializingBean和DisposableBean接口

通过实现InitializingBean接口的afterPropertiesSet()方法可以在Bean属性值设置好之后做一些操作,

实现DisposableBean接口的destroy()方法可以在销毁Bean之前做一些操作。

5.7 注入容器内置对象

有时候我们需要在 Bean 的初始化中使用 Spring 框架自身的一些对象来执行一些操作,为了让 Bean 可以获取到框架自身的一些对象,Spring 提供了一组名为*Aware的接口。

这些接口均继承于org.springframework.beans.factory.Aware标记接口,并提供一个将由 Bean 实现的set*方法,Spring通过基于setter的依赖注入方式使相应的对象可以被Bean使用。

  • ApplicationContextAware: 获得ApplicationContext对象,可以用来获取所有Bean definition的名字。

  • BeanFactoryAware:获得BeanFactory对象,可以用来检测Bean的作用域。

  • BeanNameAware:获得Bean在配置文件中定义的名字。

  • ResourceLoaderAware:获得ResourceLoader对象,可以获得classpath中某个文件。

  • ServletContextAware:在一个MVC应用中可以获取ServletContext对象,可以读取context中的参数。

  • ServletConfigAware: 在一个MVC应用中可以获取ServletConfig对象,可以读取config中的参数。

5.8 bean注入map和list

在service中分别注入IEntity 的map 和列表

//    map注入
private final Map<String, IEntity> entityMap;
//    list注入
private final List<IEntity> entityList

注意:Map的Key是实现类的名称,Value为具体的类(Value的泛型为接口名称)

entityList中就是所有实现了IEntity 的bean对象

5.9 一些周边注解

@Primary,在存在多个实现的情况下,使用@Primary可以设置缺省的注入对象

@Order 在注入List的时候可以设置顺序

@ComponentScan默认是扫描的路径是同级路径及同级路径的子目录

5.10 导入beanDefinition

@Component
public class UnionPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
    //创建BeanDefinition对象
        BeanDefinition beanDefinition =
                BeanDefinitionBuilder.rootBeanDefinition(UnionServiceImpl.class).getBeanDefinition();
        //设置是否单例
        beanDefinition.setScope("singleton");
        beanDefinitionRegistry.registerBeanDefinition("unionService", beanDefinition);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    }
}

在服务启动之后,spring会自动创建bean对象,可以直接使用

6、总结

差不多该讲的都讲了,下面这幅图应该看的懂了,如果有漏的地方可以留言

赠人玫瑰,手留余香,求关注,点赞,收藏

最后推荐1本书

分布式中间件核心原理与RocketMQ实战技术一本通:实战案例+操作步骤+执行效果图,手把手教你吃透分布式中间件技术,轻松实现从小白到大牛的职业跃迁!

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

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

相关文章

Spring Security在前端后端分离项目中的使用

Spring Security 是 Spring 家族中的一个安全管理框架&#xff0c;可以和Spring Boot项目很方便的集成。Spring Security框架的两大核心功能&#xff1a;认证和授权 认证&#xff1a; 验证当前访问系统的是不是本系统的用户&#xff0c;并且要确认具体是哪个用户。简单的理解就…

全网最详细的mybatis plus 条件构造器queryWrapper学习,比如and(),eq(),or(),like(),between(),orderByAsc()等方法以及分页操作

文章目录1. 引言2. 结构关系3. 环境配置3.1 引入jar包3.2 创建数据源3.2 创建User实体类3.4 创建UserMapper类3.5 创建UserService类4. 操作演示5. 注意事项1. 引言 mybatis大家都有使用过&#xff0c;既面向对象又灵活可配。不友好的地方是&#xff0c;会随着使用出现大量xml…

C++之缺省参数以及C++的输入输出

文章目录前言一、缺省参数的定义二、缺省参数的分类1.全缺省参数2.半缺省参数三、缺省参数的注意事项1. 半缺省参数必须从右往左依次来给出&#xff0c;不能间接给缺省值2. 缺省参数不能在函数声明和定义中同时出现3. 缺省值必须是常量或者全局变量4. C语言不支持四、C的输入&a…

考虑实时市场联动的电力零售商鲁棒定价策略(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

JavaEE初阶第三课:网络初识

欢迎来到javaee初阶的第三课&#xff0c;这节课我会带大家来初识网络 荔枝目录1.认识IP和端口1.1 IP1.2端口2.认识协议2.1协议分层&#xff08;TCP/IP协议&#xff09;2.2封装与分用2.3两台主机之间的网络通信流程&#xff08;非同一网段&#xff09;3.其他常见名词 解释3.1客户…

电脑老是蓝屏是什么原因?怎么修复蓝屏

电脑老是蓝屏是什么原因&#xff1f;其实电脑蓝屏的原因是有很多种的&#xff0c;每个地方出问题都会导致电脑蓝屏&#xff0c;所以我们要想知道蓝屏的原因&#xff0c;那么就需要一步步的去检测&#xff0c;去排除掉一些可能&#xff0c;才能得出正确的蓝屏原因的答案。 一.什…

MATLAB 数组计算

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

Java字典注解的简单实现(AOP)

需求来源 在开发过程中&#xff0c;必不可少会用到字典&#xff0c;例如&#xff0c;数据库字段性别字段可能是这样的&#xff1a;1&#xff1a;男&#xff1b;2&#xff1a;女&#xff0c;在数据存储的时候用1和2&#xff0c;但是在前端展示的时候需要使用男和女&#xff0c;…

有没有人像我一样每次面对sql都很痛苦

今天又操作了一遍sql&#xff0c;这世界上有没有人像我一样&#xff0c;每一次面对mysql都是一次痛苦的经历。 不知道别人怎么想&#xff0c;反正我是这样的。使用mysql从来没有让我快乐过。在数据库里面&#xff0c;最喜欢mongo&#xff0c;当然我也只会mongo。但是每一次使用…

NL-meals、BM3D

常用的高斯滤波或者均值滤波相对都比较简单&#xff0c;即每个窗口的滤波核都是一样的。稍微复杂一些保边滤波如&#xff0c;双边滤波和导向图滤波等。这里介绍几种ffmpeg里面包含的相对比较复杂的滤波算法。计算量不可谓不小。可以通过ffmpeg查看源码实现过程&#xff0c;这里…

RHCE(防火墙)

文章目录一、什么是防火墙二、iptables三、firewalld四、作业一、什么是防火墙 防火墙&#xff1a;防火墙是位于内部网络和外部网络之间的屏障&#xff0c;它按照系统管理员预先定义的规则来控制数据包的进出 防火墙可以分为硬件防火墙和软件防火墙。硬件防火墙是由厂商设计好的…

LongAdder/LongAccumulator类分析

一、LongAdder简介 1.下图是JDK-API文档的的截图信息 我们可以得知这两个类都是1.8开始提供的&#xff0c;并且都具有顶级的并发性。这两类的区别点主要在于LongAdder初始值为0&#xff0c;只能做累加操作&#xff0c;而LongAccumulator可以完成一些复杂的计算&#xff0c;本…

软件设计师考试整理-0-前言

1. 整理初衷 2022年下半年的软考成绩出来了&#xff0c;查了一下&#xff0c;上午58分&#xff0c;下午61分&#xff0c;虽然不高&#xff0c;但是也过了&#xff0c;还是值得开心的&#xff0c;毕竟在最初报考的时候&#xff0c;会的知识点寥寥无几。 先解释下为什么我会报考…

富勒烯C60,131159-39-2,水溶性富勒烯,CARBON C60

产品描述&#xff1a;富勒烯C60与金刚石、石墨是碳的三种同素异形体&#xff0c;富勒烯分子是一种由60个碳原子结合形成的稳定分子&#xff0c;它具有60个顶点和32个面&#xff0c;其中12个为正五边形&#xff0c;20个为正六边形&#xff0c;它形似足球&#xff0c;所以又称为富…

OpenMMLab AI实战营Day2 图像分类

目录 一、图像分类 二、卷积神经网络 三、超越ResNet的图像分类模型 1、神经结构搜索 2、Transformer 3、ConvNext 四、轻量化神经网络 五、Vision Transformer 六、模型学习 七、学习率与优化器调整策略 八、数据增强 一、图像分类 图像分类&#xff1a;识别图像中…

网络骗局丨典型案例分析,大家一起来避雷!

作者&#xff1a;黑蛋因为疫情的困扰&#xff0c;总体经济都不是很好&#xff0c;春节前后&#xff0c;网络诈骗高发期&#xff0c;以下是几种典型案例&#xff0c;一起来看看。比较常见的有以下几种&#xff1a;1、网络购物骗局小红在某平台网购一件产品&#xff0c;几天后&am…

Nacos+Springcloud+mybatis-plus+oracle的整合

NacosSpringcloudmybatis-plusoracle的整合 1、项目结构 2、父类的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance&q…

shell脚本基本使用

目录 1.是什么&#xff1f; 2.写法 3.shell脚本语法 3.1第一个shell脚本 3.2交互式shell脚本 3.3shell脚本的数值计算 3.4test命令 3.5中括号【】判断符 3.6默认变量 4.shell脚本条件判断 4.1 if fi 4.2 if then else 4.3 if elif else 4.4 case 5.shell脚本函数…

Linux 学习笔记 正则、管道、进程与任务定时

一、筛选与搜索 1.1 grep 命令 筛选数据 grep 是 Globally search a regular expression and print 的缩写。意思是全局搜索一个正则表达式&#xff0c;并且打印。 考虑这样的一个名为 a.txt 的文件&#xff1a; 执行 grep apple ./a.txt 即可匹配所有含有 apple 的字符 默认…

IDEA搭建Finchley.SR2版本的SpringCloud父子基础项目-------zuul和SpringConfig

1.Zuul是什么 Zuul包含了对请求的路由和过滤两个最主要的功能&#xff1a; 其中路由功能负责将外部请求转发到具体的微服务实例上&#xff0c;是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预&#xff0c;是实现请求校验、服务聚合等功能的基础. Zu…