Spring Boot源码(四):Bean装配

为了演示Spring中对象是如何创建并放到spring容器中,这里新建一个maven项目:

其中pom.xm文件中只引入了一个依赖:

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.9.RELEASE</version>
        </dependency>
    </dependencies>

其实我们只需要这一个,不过spring还是会自动导入他别的依赖,例如spring core,spring aop:

需要说明的是我这里并没有建spring boot项目,只是引入一个spring context依赖的maven项目。

新建一个config配置类,并没有@Configuration注解:

@ComponentScan("component")
public class MyConfig {
}

只有一个@ComponentScan注解,去扫描指定包。

新建一个类(bean),只有@Component注解:

@Component
public class People {
}

新建Test类,此类去创建spring context(spring上下文,或者说是spring容器):

import config.MyConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    public static void main(String[] args) {
        //通过注解配置类初始化 spring上下文
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(MyConfig.class);
        //还有一种通过xml来初始化 spring上下文,这里就不介绍了。
        //ClassPathXmlApplicationContext
        System.out.println(annotationConfigApplicationContext.getBean("people"));
    }
}

我们只关注bean的创建,所以在 new AnnotationConfigApplicationContext(MyConfig.class) 时会去扫描类,然后实例化。

this()调用此类的构造器:

这个reader和scanner和这里bean实例化没有关系,是一些扩展。我们关注他的父类构造器:

可见this()方法就是建立一个beanFactory工厂,至于细节暂时不去深入。

register()方法作用是新建一个BeanDefinition。

BeanDefinition顾名思义就是spring定义的一个描述bean的类,这个是接口,其描述类的属性由其子类扩展,比如class,lazy(懒加载)等等:

上面时AbstarctBeanDefinition类下的属性。spring根据我们的类(不管是@Service,@Controller,或者是通过@Bean方式),生成对应的BeanDefinition对象。

再把它放到一个Map中:

registerBeanDefinition有三个实现方法,不管哪个都有下面这一句:

即把各个BeanDefinition对象放入beanDefinitionMap中去,而这些map的集合就是spring 的容器。

所以register()做了两件事:

1:生成对应BeanDefinition对象;

2:放入beanDefinitionMap中。

最后再来看refresh()方法:

这个方法是spring中最复杂也是最重要的方法:

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 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);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // 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 (BeansException 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 {
                // Reset common introspection caches in Spring‘s core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

其中invokeBeanFactoryPostProcessors()方法需要讲一讲,详见下一篇。

原文地址:https://www.cnblogs.com/SunSAS/p/12292782.html

时间: 2024-10-04 02:42:48

Spring Boot源码(四):Bean装配的相关文章

曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean definition的?

写在前面的话 相关背景及资源: 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享 工程代码地址 思维导图地址 工程结构图: 大体思路 总体来说,bean definition是什么,我们前面几讲,说了个大概了:目前,我们将聚焦于怎么获取bean definition. 我们这次做个实验,就是将bean definition(一共两个bean,有依赖关系,依赖是手动指定的)定义在json文件内,然后自定义一个applicat

曹工说Spring Boot源码(5)-- 怎么从properties文件读取bean

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(9)-- Spring解析xml文件,到底从中得到了什么(context命名空间上)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(18)-- Spring AOP源码分析三部曲,终于快讲完了 (aop:config完整解析【下】)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

Spring Boot源码中模块详解

Spring Boot源码中模块详解 一.源码 spring boot2.1版本源码地址:https://github.com/spring-projects/spring-boot/tree/2.1.x 二.模块 Spring Boot 包含许多模块,以下是一些简单的概述: 1,spring-boot 为Spring Boot其他部分功能提供主要的lib包,其中包含:(1)SpringApplication类提供了静态便利的方法使编写独立的SpringApplication更加容易.它唯一的任

曹工说Spring Boot源码(8)-- Spring解析xml文件,到底从中得到了什么(util命名空间)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(13)-- AspectJ的运行时织入(Load-Time-Weaving),基本内容是讲清楚了(附源码)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(15)-- Spring从xml文件里到底得到了什么(context:load-time-weaver 完整解析)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(16)-- Spring从xml文件里到底得到了什么(aop:config完整解析【上】)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de