Spring ApplicationContext初始化过程

Spring-01篇章

一、Spring 简介

Spring是一个开源的Java平台,它提供了全面的基础设施支持来帮助Java开发者更容易地开发Java应用程序。Spring框架的核心特点是依赖注入(DI)和面向切面编程(AOP),这些使得开发者能够以更简洁和模块化的方式构建应用程序。

Spring的主要特点包括:

  1. 依赖注入:Spring通过依赖注入(DI)来实现组件之间的解耦,这意味着组件的依赖关系由Spring容器在运行时注入,而不是在代码中硬编码。

  2. 面向切面编程:Spring支持面向切面编程(AOP),允许开发者将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来。

  3. 事务管理:Spring提供了声明式事务管理,使得事务管理更加简单和透明。

  4. 数据访问:Spring提供了对各种数据访问技术的集成,如JDBC、Hibernate、JPA等。

  5. Web支持:Spring提供了对多种Web框架的集成,如Spring MVC、Spring WebFlux等。

  6. 安全性:Spring Security是一个功能强大的安全和认证框架,可以与Spring应用程序集成。

  7. 测试:Spring提供了对单元测试和集成测试的支持,使得测试Spring应用程序更加容易。

  8. 模块化:Spring框架是高度模块化的,开发者可以根据需要选择使用特定的模块。

  9. 集成:Spring提供了与其他企业级技术的集成,如消息传递、任务调度等。

  10. 社区和文档:Spring拥有一个活跃的社区和丰富的文档资源,为开发者提供了大量的学习材料和支持。

Spring框架广泛应用于企业级Java应用开发,它简化了Java应用的开发,提高了代码的可维护性和可测试性。随着时间的推移,Spring已经发展成一个庞大的生态系统,包括Spring Boot、Spring Cloud等子项目,进一步简化了微服务架构的开发和部署。

二、使用及源码讲解

1.导入依赖包

本次演示使用的jdk版本为11,spring版本为 5.3.39

以下是pom文件示例

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.simple.code.generator</groupId>
  <artifactId>spring-simple</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring-simple</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.39</version>
    </dependency>

  </dependencies>
</project>

然后我们创建一个HelloService的接口用于演示,并为接口创建实现类,具体代码如下:

HelloService

package com.simple.code.generator.service;

public interface HelloService {

    void sayHello();

}

HelloServiceImpl

package com.simple.code.generator.service.impl;

import com.simple.code.generator.service.HelloService;

public class HelloServiceImpl implements HelloService {

    public void sayHello() {
        System.out.println("hello world !!!");
    }
}

编写一个main函数进行测试执行,并查看输出结果。

package com.simple.code.generator;

import com.simple.code.generator.service.HelloService;
import com.simple.code.generator.service.impl.HelloServiceImpl;

public class Main {

    public static void main(String[] args) {
        HelloService helloService = new HelloServiceImpl();
        helloService.sayHello();
    }

}

整体结构目录见截图

执行后接下来我们需要思考的问题是,已经引入了spring依赖包,为什么还要进行new对象的操作来获取方式呢,我们将代码稍加改造,在HelloServiceImpl增加@Service注解

package com.simple.code.generator.service.impl;

import com.simple.code.generator.service.HelloService;
import org.springframework.stereotype.Service;

@Service
public class HelloServiceImpl implements HelloService {

    public void sayHello() {
        System.out.println("hello world !!!");
    }
}

将Main入口调用改成如下,修改后再次执行,发现我们不再需要显示的去进行new对象调用,直接从容器中获取对象即可访问到sayHello的内容。接下来我们将通过这个案例去分析讲解什么是AnnotationConfigApplicationContext,以及HelloService是如何被加载初始化的。

package com.simple.code.generator;

import com.simple.code.generator.service.HelloService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

    public static void main(String[] args) {
        //com.simple.code.generator 对应需要扫描的包名
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.simple.code.generator");
        context.getBean(HelloService.class).sayHello();
    }

}

2.HelloService注册到容器过程

我们看到AnnotationConfig ApplicationContext的类图如下,接下来我们将围绕ResourceLoader和BeanFactory讲解Context的初始化过程。

如图展示,我们在创建AnnontationConfigApplicationContext在创建的时候会同时创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。创建后紧跟着会调用ClassPathBeanDefinitionScanner的scan函数扫描我们创建时传入的包路径进行代码文件扫描,扫描后通过GenericApplicationContext的registerBeanDefinition和 registerAlias将找到的文件注册到context容器中,到这一步我们已经看到并掌握了容器扫描以及注册bean的过程,感兴趣的可以随着流程图看下源码中的细节部分。接下来我们继续分析容器的启动过程。

我们继续查看refresh函数,它会执行父类的refresh函数启动spring context容器,并将第一步扫描到的类信息进行初始化,核心代码如下。到这里我们从class的扫描到装载以及初始化容器的过程简单的带大家查看了一遍。

@Override
	public void refresh() throws BeansException, IllegalStateException {
		this.startupShutdownLock.lock();
		try {
			this.startupShutdownThread = Thread.currentThread();

			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (RuntimeException | Error ex ) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				contextRefresh.end();
			}
		}
		finally {
			this.startupShutdownThread = null;
			this.startupShutdownLock.unlock();
		}
	}

总结

以上就是今天要讲的内容,本文仅仅简单介绍了spring的使用,而spring提供了IOC、AOP、DI等功能我将会在后续的文章中一一详细描述。如描述有误还望大家不吝赐教,感谢各位耐心观看!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【H2O2|全栈】JS入门知识(一)

目录 JS入门 前言 准备工作 JS标签和文件 变量 数据类型 字符串 变量的交换 数据类型获取 数据类型转换 面试题 提问框和提示框 提问框 提示框 ​编辑​编辑控制台输出 ​编辑转义字符 结束语 JS入门 前言 本系列博客主要分享JavaScript的基础语法知识&…

RNA-seq全流程

第一部分&#xff1a;脚本的初始设置与参数解析 #!/bin/bash# 检查输入参数 if [ "$#" -lt 1 ]; thenecho "Usage: $0 -f <sample_file> -d <data_directory> -s <script_directory> -g <group_file>"exit 1 fi# 使用 R 语言的 a…

2025推荐选题|基于Springboot和vue的智慧阅读管理系统

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…

Java - WebSocket

一、WebSocket 1.1、WebSocket概念 WebSocket是一种协议&#xff0c;用于在Web应用程序和服务器之间建立实时、双向的通信连接。它通过一个单一的TCP连接提供了持久化连接&#xff0c;这使得Web应用程序可以更加实时地传递数据。WebSocket协议最初由W3C开发&#xff0c;并于2…

【CSS】houdini自定义CSS属性实现渐变色旋转动画

现有一段代码&#xff0c;在不旋转整个元素的前提下&#xff0c;渐变背景无法应用动画 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initia…

专业模拟训练头显,Varjo XR-4 如何开启虚拟仿真新模拟时代

虚拟仿真模拟训练是提升技能熟练度与工作安全性的有效解决方案&#xff0c;Varjo XR-4作为专业模拟训练头显&#xff0c;凭借其出色的技术特性和性能&#xff0c;正在引领虚拟仿真模拟训练进入一个全新的时代。 一、卓越的视觉体验 高分辨率显示器&#xff1a;Varjo XR-4配备…

计算机毕业设计 基于Python的美术馆预约系统的设计与实现 Python毕业设计 Python毕业设计选题【附源码+安装调试】

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

三子棋(C 语言)

目录 一、游戏设计的整体思路二、各个步骤的代码实现1. 菜单及循环选择的实现2. 棋盘的初始化和显示3. 轮流下棋及结果判断实现4. 结果判断实现 三、所有代码四、总结 一、游戏设计的整体思路 &#xff08;1&#xff09;提供一个菜单让玩家选择人机对战、玩家对战或者退出游戏…

大厂面试真题-组合和聚合的区别是什么

组合和聚合比较类似&#xff0c;二者都表示整体和部分之间的关系。 聚合关系的特点是&#xff1a;整体由部分构成&#xff0c;但是整体和部分之间并不是强依赖的关系&#xff0c;而是弱依 赖的关系&#xff0c;也就是说&#xff0c;即使整体不存在了&#xff0c;部分仍然存在…

Zabbix监控vCenter虚拟机

1. vcenter上配置snmp agent 如果配置 vCenter Server Appliance SNMP 代理以用于轮询,则它可以侦听和响应来自 SNMP 管理客户端系统的请求,如 GET、GETNEXT 和 GETBULK 请求. 使用root身份进入vcenter命令行,开启snmp代理 Command> snmp.enable Command> snmp.set…

正则表达式 | Python、Julia 和 Shell 语法详解

正则表达式在网页爬虫、脚本编写等众多任务中都有重要的应用。为了系统梳理其语法&#xff0c;以及 Python、Julia 和 Shell 中与正则表达式相关的工具&#xff0c;本篇将进行详细介绍。 相关学习资源&#xff1a;编程胶囊。 基础语法 通用语法 在大多数支持正则表达式的语…

24/10/14 视觉笔记 图像拼接融合

图像拼接分为四步 1.特征点提取 2.特征点匹配 3.仿射矩阵计算 4.图像拼接与融合 1.特征提取 找到图像中具有显著性信息点&#xff0c;并计算该点的特征表达 def detectAndDescrible(img):#构建STFT特征检测器sift cv2.SIFT_create()#特征提取kps,features sift.detectA…

3-3 AUTOSAR RTE 对SR Port的实现

返回总目录->返回总目录<- 目录 一、前言 二、显式访问 三、隐式访问 四、队列调用(Queued) 五、无效数据元素 一、前言 RTE作为SWC和BSW之间的通信机构,支持Sender-Receiver方式实现ECU内及ECU间的通信。 对于Sender-Receiver Port支持三种模式: 显式访问:若…

京东零售数据湖应用与实践

作者&#xff1a;陈洪健&#xff1a;京东零售大数据架构师&#xff0c;深耕大数据 10 年&#xff0c;2019 年加入京东&#xff0c;主要负责 OLAP 优化、大数据传输工具生态、流批一体、SRE 建设。 当前企业数据处理广泛采用 Lambda 架构。Lambda 架构的优点是保证了数据的完整性…

LeetCode|70.爬楼梯

这道题很像斐波那契数列&#xff0c;但是初始值不同&#xff0c;也有动态规划的解法&#xff0c;但是一开始我想到的是递归写法。现在我们站在第n阶台阶&#xff0c;那么&#xff0c;我们上一步就有两种可能&#xff1a;1、我们从第n-1阶台阶走一步上来的&#xff1b;2、我们从…

弹出“xinput1_3.dll文件缺失”的错误要怎么处理?一键修复xinput1_3.dll

当你尝试打开游戏或应用时&#xff0c;如果弹出“xinput1_3.dll文件缺失”的错误&#xff0c;请记得及时处理。这个文件是DirectX中用于处理游戏控制器输入的关键组件。这个问题可以通过几个简单的步骤轻松解决。本指南将教你如何快速恢复或替换丢失的xinput1_3.dll文件&#x…

免费Excel工作表同类数据合并工具

下载地址&#xff1a;https://pan.quark.cn/s/81b1aeb45e4c 在 Excel 表格里&#xff0c;当我们试图手动将多行同类数据合并为一行时&#xff0c;会遭遇诸多棘手的困难以及繁杂的操作流程。在确定哪些数据属于可合并的同类数据时&#xff0c;单纯依靠人工进行对比&#xff0c;极…

SQL数据库刷题sql_day33(连续3次为球队得分的球员名单)

描述 两支篮球队进行了激烈的比赛&#xff0c;比分交替上升。比赛结束后&#xff0c;你有一个两队分数的明细表&#xff08;名称为“分数表”&#xff09;。 表中记录了球队、球员号码、球员姓名、得分分数及得分时间。现在球队要对比赛中表现突出的球员进行奖励。 问题&#x…

用最短长度的绳子把整个花园围起来

给定一个数组 trees&#xff0c;其中 trees[i] [xi, yi] 表示树在花园中的位置。 你被要求用最短长度的绳子把整个花园围起来&#xff0c;因为绳子很贵。只有把 所有的树都围起来&#xff0c;花园才围得很好。 返回恰好位于围栏周边的树木的坐标。 示例 1: 输入: points […

MySQL 的数据类型

1.整数类型 1.1 tinyint tinyint 为小整数类型&#xff0c;存储空间为1个字节&#xff08;8位&#xff09;&#xff0c;有符号范围-128 ~ 127&#xff0c;无符号范围 0 ~ 255,此类型通常在数据库中表示类型的字段&#xff0c;如某一字段 type 表示学科,其中 “type1” 表示语文…