为了演示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()方法需要讲一讲,详见下一篇。

Spring Boot源码(五):BeanFactoryPostProcessor和BeanPostProcessor

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

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

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  2. 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享

    写在前面的话&&About me 网上写spring的文章多如牛毛,为什么还要写呢,因为,很简单,那是人家写的:网上都鼓励你不要造轮子,为什么你还要造呢,因为,那不是你造的. 我不是要 ...

  3. 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享 工程代码地址 思维导图地址 工程结构图: 正 ...

  4. 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享 工程代码地址 思维导图地址 工程结构图: 大 ...

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

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享 工程代码地址 思维导图地址 工程结构图: 大 ...

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

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  7. Spring Boot源码(六):Bean的创建详解

    继续之前的项目: People加上无参构造方法: @Component public class People { // private User user; public People(){ Sys ...

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

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  9. # 曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

随机推荐

  1. jenkins集成gitlab

     一.配置jenkins 1.安装Gitlab Hook Plugin )生成随机token 在系统中生成 openssl rand -hex 0f2a47c861133916d2e299e3 )创建 ...

  2. 15、WAN

    WAN wide area network 覆盖较大地理范围的数据通信网络使用网络提供商和电信公司所提供的传输设施传输数据 通过不同WAN协议,将LAN延伸到远程站点的其他LAN广域网接入处于OSI七 ...

  3. gdiplus exception

    <span style="font-size:14px;">#include <windows.h> #include <gdiplus.h> ...

  4. BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)

    题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...

  5. React+Echarts简单的封装套路

    今天我们来介绍一下React中,对Echarts的一个简单的封装. 首先在我们的React项目中,想使用Echart包,首先需要先安装它,安装代码如下,任选一个就可以 cnpm install ech ...

  6. Java中类的关系

    在java里类的关系大致分为三种, 1.继承(a is b):继承extends,实现implement 2.包含(a has b):组合>聚合>关联.关系亲密度越来越小,一个类在另一个类 ...

  7. 苹果系统iOS、macOS应用管理机制

    iOS.macOS系统应用管理机制 苹果系统包括:iOS.macOS.watchOS.tvOS.应用软件的生命周期为:开发.上线.安装.使用.卸载.这篇文档将从应用生命周期的各个环节介绍苹果系统对应用 ...

  8. golang 自定义结构体(与其他语言对象类似)

    /* 结构体变量: 结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正地分配内存, 因此必须在定义结构体并实例化后才能使用结构体的字段. type 类型名 struct { 字段1 字 ...

  9. 见异思迁:K8s 部署 Nginx Ingress Controller 之 kubernetes/ingress-nginx

    前天才发现,区区一个 nginx ingress controller 竟然2个不同的实现.一个叫 kubernetes/ingress-nginx ,是由 kubernetes 社区维护的,对应的容 ...

  10. Day4前端学习之路——背景边框列表链接和更复杂的选择器

    课程目标 掌握 CSS 稍微复杂的一些选择器,还有背景,边框等一些 CSS 样式属性 主要内容: 背景属性 边框 列表 链接 其他选择器 选择器概览:https://www.w3school.com. ...