浅谈Spring中的一些技术

news/2024/7/9 6:03:28 标签: spring, java, 后端, ioc容器, Spring IOC容器

一、前言

        在学习Spring或者SpringBoot原理时,心里要始终想着一件事情:只有把对象(也可以称之为组件、bean)放入到Spring的IOC容器中,才能使用Spring为我们提供的一系列强大功能。

二、一些说明

        在学习Spring或者SpringBoot的过程中,我们经常听到 <组件>、<bean>这两个词,那么这两个词指代什么呢?个人的一些浅显理解:你就把这两个词理解成普通的Java对象就可以,比如你自己写的一个User类(你创建一个User对象,把其添加到Spring的IOC容器中,这个User对象就可以称之为一个User组件,或者称之为一个bean组件),你创建了第三方的某个类的对象,然后把其放入Spring的IOC容器中,就可以这样说:我在容器中放入了某个类的一个组件。

三、添加组件(bean)到容器中

       如何把自己写的对象(或称之为组件,或称之为bean)或者第三方组件放入到IOC容器中呢?有四种方式:

3.1 包扫描 + 组件标注注解

        即在某个配置类(配置类指的是标注了@Configuration注解的类)上标注@ComponentScan(basePackages={"包名1","包名2"}), 然后再类上标注@Component、@Repository、@Service、@Controller等注解的方式。

        注意:此种方式局限于想要把自己写的类添加到IOC容器中。

3.2 @Bean

        在配置类中使用@Bean的方式给容器中导入一个组件。使用这种方式可以把第三方包中的组件导入到IOC容器中,让IOC容器帮我们管理第三方的组件,当需要使用第三方组件时,再从容器中获取就好了。

3.3 @Import

3.3.1 @Import导入普通组件

        @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名。比如你创建了一个com.example.User类,使用@Import(value={User.class})就可以给容器中导入一个User组件。

3.3.2 @Import(value={xxxImportSelector.class})

        可以实现ImportSelector接口,然后实现接口中的 selectImports方法,让这个方法返回需要导入容器中的组件的全限定类名数组。然后使用 @Import(value = {MyImportSelector.class})的方式可以一次性给容器中导入多个组件。

3.3.3 @Import(value={xxxImportBeanDefinitionRegistrar.class})

        可以实现 ImportBeanDefinitionRegistrar 接口,然后实现接口中的 registerBeanDefinitions 方法,在方法的实现中手动注册 BeanDefinition 到IOC容器中。然后使用 @Import(value = {MyImportBeanDefinitionRegistrar.class})的方式给容器中导入组件。

3.4 使用FactoryBean

        使用Spring提供的 FactoryBean(工厂Bean):

         1)、默认获取到的是工厂bean调用getObject创建的对象

         2)、要获取工厂Bean本身,我们需要给id前面加一个&前缀

二、单例还是多例

        导入到容器中的组件,是单例还是多例呢?默认存放在Spring IOC容器中的组件都是单例的,当然我们也可以控制放入IOC容器中的组件是否单例还是多例。比如在使用 @Bean给容器中放入组件时,可以使用 @Scope(value = "singleton") 或者 @Scope(value = "prototype") 控制你要放入到IOC容器中的组件是否为单例。

三、Bean的生命周期

        把组件放入到IOC容器中,就意味着我们把一个对象交给了Spring 的IOC容器管理。每一个组件在IOC容器中都是有生命周期的。组件的生命周期概况起来有如下四个阶段:

bean的对象创建(调用bean的构造方法创建对象) -> 给bean进行属性赋值 -> 后置处理器的前置处理方法 -> 初始化 -> 后置处理器的后置处理方法 -> 销毁bean

bean对象创建,主要分为单实例bean的创建和多实例bean的创建:

1)单实例bean:在容器启动时创建所有的单实例bean;

2)多实例bean:在每次获取bean组件时,都会创建新的bean。

bean的属性赋值(见第四小节)

后置处理器的前置处理方法 -> 初始化 -> 后置处理器的后置处理方法 -> 销毁bean

针对bean的初始化前后,还可以做一些其他工作,有BeanPostProcessor来完成.

BeanPostProcessor.postProcessBeforeInitialization (在初始化方法执行之前进行后置处理工作
<调用初始化方法>
BeanPostProcessor.postProcessAfterInitialization  (在初始化方法执行之后进行后置处理工作
<销毁bean>

其中bean的初始化和销毁方式有如下几种:

(a) 通过@Bean注解指定 initMethod和destroyMethod 
(b) 让bean实现 InitializingBean 和 DisposableBean 接口
(c) JRS250提供的注解:
     @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
     @PreDestroy:在容器销毁bean之前通知我们进行清理工作 

四、属性赋值

        在给组件中的属性赋值时,我们可以使用@Value的方法,@Value可以写普通字符串,SpEL表达式,可以从配置文件中通过${xxx}的方式取值,需要把配置文件通过 @PropertySource引入进来,使配置文件中k/v键值对被Spring读取到运行时环境变量里面;

五、组件之间的依赖注入

        组件之间会有依赖关系,比如xxxService依赖xxxDao组件,可以Spring或Java规范为我们提供的组件注入功能,如@Autowired + @Qualifier指定要注入的组件,Java规范里面的@Resource和@Inject注解。

        疑问1:为什么标注了@Autowired注解之后,组件就自动给其属性进行了赋值呢?这就是组件注入的后置处理器(xxxPostProcessor)在底层进行工作。 

        疑问2:Spring在底层给IOC容器中注入了一些有用的组件,如果我们想把这些底层组件注入到我们自定义的组件中该怎么做呢?可以让自定义的组件实现Spring给我们提供的各种xxxAware接口,然后Spring在把我们自定义的组件添加到容器中的时候,会应用xxxAware对应的后置处理器,把其底层的组件注入到我们自定义的组件中。

        疑问3:我还想让一些组件在特定条件下才注入到容器中,而不是无脑往容器中注入,该怎么办呢?可以使用@Import的,指定自定义的实现了ImportSelector接口的类,在自定义的实现类中进行进行条件控制,从而控制是否要导入哪些组件,还可以通过指定@Condition注解,需要我们自己实现 Condition接口,在接口中判断是否要导入某些组件。


http://www.niftyadmin.cn/n/5538558.html

相关文章

基于正点原子FreeRTOS学习笔记——时间片调度实验

目录 一、时间片调度介绍 二、实验演示 1、宏修改 1.1、滴答定时器宏 1.2、调度器宏 2、实验程序 2.1.1、任务1&#xff0c;任务2不加临界区程序 2.1.2 实验现象 2.2.1、任务1&#xff0c;任务2加临界区程序 2.2.2 实验现象 一、时间片调度介绍 时间片&#xff1a;同…

EasyExcel导入合并单元格数据

1.EasyExcel.read 方法 这里在read的时候要注意&#xff0c;增加这个extraRead(CellExtraTypeEnum.MERGE)来解析合并单元格的信息 ImportListener listener new ImportListener();try {EasyExcel.read(file.getInputStream(), ImportDto.class, listener).headRowNumber(1).e…

万和-集训刷题1

leetcode 2 两数之和 class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode p1l1;ListNode p2l2;int next0;ListNode headnew ListNode(-1);ListNode tailhead;while (p1!null||p2!null){int n1p1!null?p1.val:0;int n2p2!null?p2.val:0;i…

7月6日 VueConf 技术大会即将在深圳举办

7月6日&#xff0c;VueConf 2024 即将在深圳召开&#xff0c;本次大会正值 Vue.js 十周年&#xff0c;旨在聚焦 Vue.js 社区的成员&#xff0c;分享最新的技术动态、经验以及创新实践。 本次参与 VueConf 大会的是来自全球 Vue.js 核心团队成员、行业专家及前端开发者。其中&a…

将CSV、Excel、XML文件转换为MySQL数据库

在平时的工作中&#xff0c;经常会遇到需要将文件数据导入到数据库中的情况。有些客户之前可能只使用Excel表格作为记录工具&#xff0c;但当数据量达到一定程度或者需要将数据导入到其他系统中时&#xff0c;就会很emo,因为Excel表格虽然方便&#xff0c;但在数据处理和管理方…

Hadoop3:Yarn的Tool接口案例

一、需求 依然以wordcount案例为基础&#xff0c;进行开发 我们知道&#xff0c;用hadoop自带的example.jar执行wordcount 命令如下 hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount -D mapreduce.job.queuename…

用Redis实现排行榜的详细用例

下面是一个使用 Redis 的 Sorted Set 数据结构实现的排行榜系统的详细示例&#xff0c;包括查看全部排名、获取单个排名、增加分数等操作。我们将使用 Lettuce 库来与 Redis 进行交互。 项目结构 pom.xml&#xff1a;添加必要的依赖。LeaderBoardService&#xff1a;实现排行…

在CenteOs7上安装mysql8.0(Super详细版)

在CenteOs7上安装mysql8.0 为什么用Mysql8.0&#xff1f;如何下载下载地址需要提前准备下载步骤 服务器上安装如何上传到服务器&#xff1f;通过wget下载到服务器并解压 开始安装非必须安装如果全部安装执行顺序 安装完后&#xff0c;启动mysql使用“systemctl”检测mysqld服务…