Spring源码(二)Spring容器初始化

了解专栏完整的内容,请点击跳转:
Spring Framework专栏导航页

gitee注释版源码

为了阐述得简要些,以下几篇内容都侧重于介绍注解方式的Spring容器,XML方式的略过。


什么是Spring容器

微观来说这个容器就是存储bean的Map,宏观来说(一般来说)是指ApplicationContext或者Spring框架的概念。

我们知道Spring是基于Ioc原理来管理我们的bean,让程序员解放双手,使对象的创建和使用不再犯难。
所以,Spring在启动的时候,会把我们用注解标识的bean都创建好并存起来,这个存的地方就是我们所说的容器,Spring的容器是用 Map<String, Object>结构来存我们的bean,为了解决bean之间创建时候可能有循环依赖问题,所以又加了两个Map结构,一共三个:

  • Map<String, Object> singletonObjects // 一级缓存,存放的是已完全创建完的bean
  • Map<String, Object> earlySingletonObjects // 二级缓存,存放的是已实例化但未进行属性赋值和初始化的bean
  • Map<String, ObjectFactory<?>> singletonFactories // 三级缓存,存放的value是一个函数接口 通过getObject获得bean

什么是BeanFactory

Spring有了容器,那就解决了存放的问题,那这么多奇奇怪怪的bean又该怎么创建呢?
Spring使用了简单工厂的设计模式,即用BeanFactory来生产我们的bean


什么是FactoryBean

他其实也是一种工厂,看一下这个接口就知道了。
最重要的就是getObject,可以拿到一个bean,和beanFactory功能一样。
可以供其他框架整合时候作为一个衔接纽带。

public interface FactoryBean<T> {
   

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class<?> getObjectType();

	default boolean isSingleton() {
   
		return true;
	}
}

什么是ApplicationContext

是一种特殊的BeanFactory,功能比BeanFactory强大

Springboot启动类:

ConfigurableApplicationContext contxt = SpringApplication.run(Application.class, args)

还有AnnotationConfigApplicationContext

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);

在这里插入图片描述


回归正题

好了,铺垫了一些概念,现在回到正题,Spring究竟是如何初始化的。

流程图如下:
Spring容器初始化


源码

完整代码点击这里,持续更新中


从这里开始

public class Application {
   

	public static void main(String[] args) {
   
		// 注解配置方式的spring容器 启动时候能完成单例bean的生产 供项目使用
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
		MainConfig bean = context.getBean(MainConfig.class);
		System.out.println(bean);
	}
}

AnnotationConfigApplicationContext 构造器

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   

		// 空参构造函数 (实例化bean工厂、创建bean定义读取器、创建bean定义扫描器)
		this();
		// 注册配置类(即自定义的配置类)到bean定义Map中
		register(componentClasses);
		// ioc容器刷新接口 这个是最重要的 前面都是准备工作 还没有一个bean完成创建
		refresh();
	}

在这里插入图片描述

空参构造函数

	public AnnotationConfigApplicationContext() {
   
		StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
		// 创建bean定义读取器
		this.reader = new AnnotatedBeanDefinitionReader(this);
		createAnnotatedBeanDefReader.end();
		//创建BeanDefinition扫描器
		// 这个扫描器是给程序员手动调用扫描器的 解析@ComponentScan时候,会再创建一个扫描器
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	

AnnotatedBeanDefinitionReader核心代码

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
   
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		//把ApplicationContext对象赋值给AnnotatedBeanDefinitionReader
		this.registry = registry;
		//用于处理条件注解 @Conditional
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		//注册一些内置的后置处理器 用于解析@Component、@Configuration等
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

注册配置类

public void register(Class<?>... componentClasses) {
   
		Assert.notEmpty(componentClasses, "At least one component class must be specified");
		StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
				.tag("classes", () -> Arrays.toString(componentClasses));
		// 这里跟进去
		this.reader.register(componentClasses);

		registerComponentClass.end();
	}

配置类注册的核心代码

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
   

		//存储@Configuration注解注释的类
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		//判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
   
			return;
		}

		abd.setInstanceSupplier(supplier);
		//解析bean的作用域,如果没有设置的话,默认为单例
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		//获得beanName
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		if (qualifiers != null) {
   
			for (Class<? extends Annotation> qualifier : qualifiers) {
   
				if (Primary.class == qualifier) {
   
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
   
					abd.setLazyInit(true);
				}
				else {
   
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		if (customizers != null) {
   
			for (BeanDefinitionCustomizer customizer : customizers) {
   
				customizer.customize(abd);
			}
		}

		BeanDefinitionHolder definitionHolder =
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值