SpringBoot详细讲解如何创建及刷新Spring容器bean

目录
  • 一、前期准备
    • 1.1 创建工程
    • 1.2 创建Controller
  • 二、探究过程
    • 2.1 启动类
    • 2.2 SpringApplication
    • 2.3 ApplicationContextFactory
    • 2.4 SpringApplication
    • 2.5 结论

一、前期准备

1.1 创建工程

创建springboot项目,springboot版本为2.5.0,引入spring-boot-starter-web依赖,pom文件如下:

<?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"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

1.2 创建Controller

创建一个简单的Controller用于测试

@RestController
public class HelloController {
    public void helloController() {
        System.out.println("创建了");
    }
    @RequestMapping("hello")
    public String hello() {
        return "hello";
    }
}

二、探究过程

2.1 启动类

项目的运行只需要启动类中一行简单的代码,spring容器的创建就是通过SpringApplication.run(SpringbootApplication.class, args)这一行代码实现的。

其实就是调用了静态的run方法,传入了启动类的字节码对象。

2.2 SpringApplication

run()方法

又调用了另一个run方法。

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return run(new Class[]{primarySource}, args);
}

run()方法

方法的返回值类型为ConfigurableApplicationContextApplicationContext就是Spring的容器。

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
	return new SpringApplication(primarySources).run(args);
}

我们来看看ConfigurableApplicationContext 继承结构

ConfigurableApplicationContext接口继承了ApplicationContext接口

下面我们通过debug进入run()方法中看看

run()方法

createApplicationContext()方法

容器工厂传入webApplication的类型,这个类型为Servlet应用。

Springboot可以做响应式的Web开发,这时webApplication的类型的类型就不是Servlet。

2.3 ApplicationContextFactory

这里是一个lambda表达式的写法,根据webApplicationType的类型返回对应的容器对象。

通过继承关系图可以看出,它的确是ApplicationContext

2.4 SpringApplication

run()方法,容器刷新前

看完了createApplicationContext()的过程,我们再次回到run()方法中,此时context已经创建完成。

我们观察一下context中都有些什么:

其中包含了bean工厂,bean工厂里有beanDefinitionNames和beanDefinitionMap。(与之前看的spring源码一样)

不过这里都是spring容器内置的beanDefinition对象,没有我们自定义的helloController,说明现在的容器还没有刷新。

我们现在获取不到HelloController的bean对象,当我们能获取到这个对象时,就说明容器刷新了。

run()方法,容器刷新后

继续往下运行,我们发现这行代码执行了好久,根据方法名称也可以看出它的功能就是刷新容器。

刷新后我们成功的获取到了bean对象。

此时beanDefinitionMap中包含了138个对象,刷新之前只包含5个。我们可以在里面找到helloController(Hello的H变成了小写)

refreshContext()方法

下面我们看看refreshContext()方法,其中调用了refresh()方法。

refresh()方法

refreshContext()方法中refresh(context)传入了容器对象,在这里调用了这个容器对象的refresh()方法。

后面暂时不往下看了。

2.5 结论

在启动类中调用SpringApplication的run方法时会根据容器的类型创建不同的容器对象,并调用容器的refresh方法。

到此这篇关于SpringBoot详细讲解如何创建及刷新Spring容器bean的文章就介绍到这了,更多相关SpringBoot Spring容器bean内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 关于Springboot如何获取IOC容器

    目录 Springboot项目中获取IOC容器的方式 方法一(不实用,不推荐): 方法二(强烈推荐): 总结 Springboot项目中获取IOC容器的方式 在Springboot项目中如果要获取IOC容器目前有两种方法. 方法一(不实用,不推荐): 在Springboot项目中都会存在一个SpringApplication的启动类,我们通过以下代码启动IOC容器. SpringApplication.run(Application.class, args); 其实run方法会将创建的IOC容器

  • Java SpringBoot容器注入对象详解

    目录 1.注入的方式 方式一:使用Import注解 方式二:使用@Service 或者@Component等注解注入到容器中 方式三:使用@Configuration和@Bean组合实现 2.注入是增加条件判断注解 3.构造方法时带参数注入 方式1:使用spring xml实现 方式2:使用@Autowired 方式3使用@Configuration和@Bean组合 4.对象注入时的一些总结 总结 1.注入的方式 方式一:使用Import注解 增加一个类HelloCompent package

  • SpringBoot向容器注册bean的方法详解

    目录 简介 法1:@Component 法2:@Configuration+@Bean 法3:@Import等 法4:FactoryBean 简介 本文用示例介绍SpringBoot如何向容器注册bean(即:将对象加入容器). 法1:@Component (@Controller/@Service/@Repository也可以,因为它里边包含@Component) 默认是加载和Application类所在同一个目录下的所有类,包括所有子目录下的类. 当启动类和@Component分开时,如果启

  • SpringBoot 创建容器的实现

    spring 容器的创建对应 SpringApplication 中 run 中调用的 createApplicationContext 方法.这里创建了一个 web 容器,接下就进去 prepareContext 容器准备阶段: private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners

  • springboot 项目容器启动后如何自动执行指定方法

    目录 springboot 项目容器启动后自动执行指定 springboot 容器及启动过程 问题1:为什么要启动父子两个容器? 问题2:在什么时候启动父容器? 问题3:父容器和子容器的区别? 问题4:怎么保证父容器启动过程中 问题5:容器实际通过什么来管理bean springboot 项目容器启动后自动执行指定 我们需要写一个class去让它实现ApplicationRunner,然后重写它的run方法就行了,注意类加上@Component注解 注意:这个class需要写在和Applicat

  • SpringBoot普通类获取spring容器中bean的操作

    前言 在spring框架中,是无法在普通类中通过注解注入实例的,因为sping框架在启动的时候,就会将标明交给spring容器管理的类进行实例化,并梳理他们彼此的依赖关系,进行注入,没有交给spring容器管理的普通类,是不会进行注入的,即使你使用了注入的相关注解.这个时候,如果我们需要在普通类中获取spring容器中的实例,就需要一些特定的方法,这里将整理一下如何在springboot中实现这样的方法. 创建springboot工程demo 项目结构图示 项目结构说明 service包下为de

  • 关于SpringBoot获取IOC容器中注入的Bean(推荐)

    一: 注入一个TestUtils类 package com.shop.sell.Utils; import com.shop.sell.dto.CartDTO; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TestUtils { @Bean(name="test

  • 学习SpringBoot容器功能及注解原理

    目录 1.组件添加 1.1@Configuration 1.2@Import 1.3@Conditional 2.原生配置文件引入 2.1@ImportResource 3.配置绑定 3.1@ConfigurationProperties 3.2@EnableConfigurationProperties + @ConfigurationProperties 1.组件添加 1.1@Configuration @Configuration:告诉SpringBoot这是一个配置类 配置类里面使用@B

  • SpringBoot详细讲解如何创建及刷新Spring容器bean

    目录 一.前期准备 1.1 创建工程 1.2 创建Controller 二.探究过程 2.1 启动类 2.2 SpringApplication 2.3 ApplicationContextFactory 2.4 SpringApplication 2.5 结论 参考视频:https://www.bilibili.com/video/BV1Bq4y1Q7GZ?p=6 通过视频的学习和自身的理解整理出的笔记. 一.前期准备 1.1 创建工程 创建springboot项目,springboot版本为

  • SpringBoot详细讲解静态资源导入的实现

    目录 SpringBootWeb开发 1. 静态资源导入 webjars 使用自己的静态资源 总结 2.制作特殊的首页 图标转变 Thymeleaf模板引擎 引入Thymeleaf 取值 有无转义 循环 SpringBootWeb开发 回顾一下: springboot帮助我们配置了什么,能不能进行修改,能修改哪些,能否扩展? xxxAutoConfiguration:向容器中自动配置组件 xxxProperties:自动配置类,装配配置文件中自定义的一些内容 开发要解决的问题: 导入静态资源 首

  • springBoot详细讲解使用mybaties案例

    首先创建springBoot项目,jdk选择1.8 然后倒入mybaties的相关依赖 我们用的springBoot,当然spring全家桶里面含有mybaties,所以我们直接使用升级版的mybaties-plus. 引入这3个 lombok省的我每次创建对象,都需要get.set方法,以及toString (IDEA里面也要安装lombok插件->file->setting->plugin->搜索lombok安装,完后重启idea,这样lombok在idea中不报错) myba

  • SpringBoot详细讲解多个配置文件的配置流程

    目录 配置文件加载顺序 验证 前期准备 验证配置文件加载顺序 验证属性互补 总结 一般情况下,springboot默认会在resource目录下生成一个配置文件(application.properties或application.yaml),但其实springboot允许配置多个配置文件(application.properties或application.yaml),但是这并不意味着这些配置文件一定会替换默认生成的配置文件,它们是互补的存在.如果在某些场景下需要把配置文件单独拿出来并且启动的

  • Springboot详细讲解RocketMQ实现顺序消息的发送与消费流程

    目录 一.创建Springboot项目添加rockermq依赖 二.配置rocketmq 三.新建一个controller来做消息发送 四.创建消费端监听消息消费消息 五.启动服务测试顺序消息发送与消费 如何实现顺序消息? 需要程序保证发送和消费的是同一个 Queue rocketmq默认发送的消息是进入多个消息队列,然后消费端多线程并发消费,所以默认情况,不是順序消费消息的:有時候,我们需要顺序消费一批消息,比如电商系统 订单创建.支付.完成操作,需要順序执行: RocketMQTemplat

  • Springboot详细讲解循环依赖

    目录 一.循环依赖 二.循环依赖形成条件(使用构造器注入) 三.循环依赖形成条件(@Aysnc注解的bean生成了对象的代理) 四.针对以上问题对Spring如何解决循环依赖进行详细阐述 一.循环依赖 顾名思义多个类中的依赖形成了环路,形成了类似于死锁的情况,导致springboot在启动时无法为我们创建Bean.通俗来说 就是beanA中依赖了beanB,beanB中也依赖了beanA. spring是支持循环依赖的,但是默认只支持单例的循环依赖,如果bean中依赖了原型bean,则需要加上l

  • SpringBoot详细讲解日志文件

    目录 1 日志的功能是什么? 2 如何自定义日志打印 2.1 在程序中获取日志对象 2.2 调用日志对象打印日志 2.3 查看日志打印的结果 3 日志的级别 3.1 日志级别的分类 3.2 日志级别的设置 4 日志持久化 5 更简单的日志输出 5.1 添加 lombok 依赖 5.2 输出日志 5.3 lombok 更多的注解 1 日志的功能是什么? 如果程序报错了, 却不能从控制台查看日志, 那么就不知道错误的原因了. 日志的功能 : 快速的排查和定位问题 记录用户登录的日志 记录系统的操作日

  • SpringBoot详细讲解视图整合引擎thymeleaf

    目录 1. 支持的视图技术 2. Thymeleaf 2.1 Thymeleaf语法 2.2 标准表达式 1. 变量表达式 ${…} 2. 选择变量表达式 *{…} 3. 消息表达式 #{…} 4. 链接表达式 @{…} 5. 片段表达式 ~{…} 3. 基本使用 3.1 Thymeleaf模板基本配置 3.2 静态资源的访问 3.3 完成数据的页面展示 1. 创建Spring Boot项目 2. 编写配置文件 3. 创建web控制类 4. 创建模板页面并引入静态资源文件 5.效果测试 1. 支

  • SpringBoot详细讲解通过自定义classloader加密保护class文件

    目录 背景 maven插件加密 注意事项 自定义classloader 隐藏classloader 被保护class手动加壳 总结 背景 最近针对公司框架进行关键业务代码进行加密处理,防止通过jd-gui等反编译工具能够轻松还原工程代码,相关混淆方案配置使用比较复杂且针对springboot项目问题较多,所以针对class文件加密再通过自定义的classloder进行解密加载,此方案并不是绝对安全,只是加大反编译的困难程度,防君子不防小人,整体加密保护流程图如下图所示 maven插件加密 使用自

  • SpringBoot详细讲解异步任务如何获取HttpServletRequest

    目录 原因分析 解决方案 前置条件 pom配置 requrest共享 自定义request过滤器 自定义任务执行器 调用示例 原因分析 @Anysc注解会开启一个新的线程,主线程的Request和子线程是不共享的,所以获取为null 在使用springboot的自定带的线程共享后,代码如下,Request不为null,但是偶发的其中body/head/urlparam内容出现获取不到的情况,是因为异步任务在未执行完毕的情况下,主线程已经返回,拷贝共享的Request对象数据被清空 Servlet

随机推荐