SpringBoot容器的创建和获取

HeJin大约 3 分钟源码解析SpringBoot源码

搭建SpringBoot工程

1.引入依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.6.13</version>
</dependency>

2.配置文件application.yml

server:
  port: 8888

3.主启动类。

@SpringBootApplication
public class SpringBootAnalysisApp {
    private static final Logger logger = LoggerFactory.getLogger(SpringBootAnalysisApp.class);

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(SpringBootAnalysisApp.class, args);
        User user = (User) applicationContext.getBean("user");
        logger.info("user: {}", user);
    }

    @Bean
    public User user(){
        return new User(1654324663, "张三", 28);
    }
}

我们向Spring容器中注入了一个User。先看看结果:

13:56:58.953  INFO 6796 --- [           main] com.sanfen.SpringBootAnalysisApp         : user: User{id=1654324663, name='张三', age=28}

接下来我们看看这个bean对象是怎么注册到容器的。

探究目标

SpringBoot基于Spring设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。我们想知道在SpringBoot中,Spring容器是怎么创建和获取bean的

SpringBoot中bean的创建

在Spring中,容器中bean的创建是在加载配置文件这一行代码。SpringBoot中同样是在这一行。

ApplicationContext applicationContext = SpringApplication.run(SpringBootAnalysisApp.class, args);

后面是直接从Spring容器中获取的。

image-20221230140518404
image-20221230140518404

1.进入SpringApplicationrun()方法,参数是我们主启动类的Class对象。

image-20221230140656380
image-20221230140656380

进入具体的run()方法:

image-20221230140914816
image-20221230140914816

重点关注context的填充:

image-20221230141504502
image-20221230141504502
image-20221230141702482
image-20221230141702482

执行完这行之后,context就可以获取到User对象了。进去看看。

进入refreshContext()方法:

image-20221230141849617
image-20221230141849617

进入refresh()方法:

image-20221230141954076
image-20221230141954076

这里会调用applicationContext应用上下文,也就是容器底层的refresh()方法。在Spring源码的探究中,同样是调用ApplicationContext的refresh()方法。这里就进入了Spring的部分。

2.进入ServletWebServerApplicationContextrefresh()方法。

image-20221230142359733
image-20221230142359733

3.进入AbstractApplicationContext中的refresh()方法。

image-20221230142538161
image-20221230142538161

这不就是我们看Spring的源码中,所说的那个Spring中bean的关键创建方法是AbstractApplicationContext中的refresh(),这里定义了bean的整个生命周期的代码。所以SpringBoot中Spring容器的创建跟Spring是完全一样的。只不过SpringBoot多包装了几层。

可以进行总结了:

  • SpringBoot是基于Spring实现的,所以SpringBoot中的容器就是Spring容器,底层跟Spring中的创建方式完全一样。
  • 有一个关键对象ApplicationContext,里面存储着创建的bean,我们可以从里面获取。

SpringBoot中bean的获取

SpringBoot中的容器就是Spring容器,那么可以猜测,获取bean的时候也是从Map中获取。我们详细看一下SpringBoot是怎么做的。

image-20221230143527584
image-20221230143527584

直接就进入了AbstractApplicationContext中的getBean()方法:

image-20221230143640017
image-20221230143640017

这跟Spring中bean的获取是完全一样的。同样的方法,同样的类。到这里我们应该明白了,为什么说SpringBoot是对Spring的封装。