Spring-IoC加载过程-Bean生命周期源码剖析

概述

Spring 最重要的概念是 IOC 和 AOP,其中IOC又是Spring中的根基:

在这里插入图片描述

一、AnnotationConfigApplicationContext 简单使用

我们可以使用AnnotationConfigApplicationContext来获取通过注解注入到容器中的bean。下面我们来简单测试一下:

我们先写一个配置类,里面定义要扫描的包路径:

@Configuration("com.jihu")
@ComponentScan("com.jihu")
public class AppConfig {
}

然后我们定义一个常用的bean:

@Component
public class TestGetBean {
}

然后我们再来使用annotationConfigApplicationContext来获取扫描的bean.

public class TestAnnotationConfigContext {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		System.out.println(applicationContext.getBean("testGetBean"));
	}
}


-------------------------------------------
com.jihu.bean.TestGetBean@12f40c25

Process finished with exit code 0

这样我们就可以获取到容器中的bean了。

二、Spring IoC容器的加载过程

AnnotationConfigApplicationContext类图分析

我们先来使用Idea看一下这个类的继承图:
在这里插入图片描述
可以看到它继承了很多接口,比如BeanDefinitionRegistry、AbstractApplicationContext等,拥有很多功能。

那我们就来详细的看看他是如何初始化bean和获取bean的。

1、实例化容器:AnnotationConfigApplicationContext

我们可以使用AnnotationConfigApplicationContext的构造方法来初始化容器。

// 接收一个component类的class, 这里我们一般会把自己的配置类写进入(配置类中有配置包的扫描路径等)
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		// 1、首先会调用父类的构造方法,其次调用自己的构造
			// 1.1、调用父类构造生成一个defaultListableBeanFactory:
				// public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory();}
			// 1.2、调用自己的构造初始化一个读取器AnnotatedBeanDefinitionReader和一个扫描器ClassPathBeanDefinitionScanner
		this();
		// 2、将我们传入的配置类(带有@Configuration注解)注册成一个bean
		register(componentClasses);
		refresh();
	}



public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

	//注解bean定义读取器,主要作用是用来读取被注解的了bean
	private final AnnotatedBeanDefinitionReader reader;

	//扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
	private final ClassPathBeanDefinitionScanner scanner;

	/**
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigApplicationContext() {
		//会隐式调用父类的构造方法,初始化DefaultListableBeanFactory

		//初始化一个Bean读取器
		this.reader = new AnnotatedBeanDefinitionReader(this);

		//初始化一个扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
}

无参构造方法中就是对读取器reader和扫描器scanner进行了实例化。

reader的类型是AnnotatedBeanDefinitionReader,可以看出它是一个 “打了注解的Bean定义读取器”。

scanner的类型是ClassPathBeanDefinitionScanner,它仅仅是在外面手动调用.scan方法,或者调用参数为String的构造方法,传入需要扫描的包名才会用到,像这样方式传入的配置类是不会用到这个scanner对象的。

2、实例化工厂:DefaultListableBeanFactory

当我们调用AnnotationConfigApplicationContext的构造方法的时候会调用其父类GenericApplicationContext的构造方法来初始化一个DefaultListableBeanFactory。

/**
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

我们来看一个DefaultListableBeanFactory的类图结构:
在这里插入图片描述
Spring中比较核心的是BeanFactory的实现类是DefaultListableBeanFactory。

它实现了很多接口,表示,它拥有很多功能:

  1. AliasRegistry:支持别名功能,一个名字可以对应多个别名
  2. BeanDefinitionRegistry:可以注册、保存、移除、获取某个BeanDefinition
  3. BeanFactory:Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象
  4. SingletonBeanRegistry:可以直接注册、获取某个单例Bean
  5. SimpleAliasRegistry:它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名功能
  6. ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的Bean}的映射关系
  7. HierarchicalBeanFactory:在BeanFactory的基础上,添加了获取父BeanFactory的功能
  8. DefaultSingletonBeanRegistry:它是一个类,实现了SingletonBeanRegistry接口,拥有了直接注册、获取某个单例Bean的功能
  9. ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能
  10. FactoryBeanRegistrySupport:支持了FactoryBean的功能
  11. AutowireCapableBeanFactory:是直接继承了BeanFactory,在BeanFactory的基础上,支持在创建Bean的过程中能对Bean进行自动装配
  12. AbstractBeanFactory:实现了ConfigurableBeanFactory接口,继承了FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和获取beanNames
  13. ConfigurableListableBeanFactory:继承了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory
  14. AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能
  15. DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大。

3.实例化建BeanDefinition读取器: AnnotatedBeanDefinitionReader

在AnnotationConfigApplicationContext的构造方法中实例化了一个AnnotatedBeanDefinitionReader。

public AnnotationConfigApplicationContext() {
		// 解析 @Configuration   添加注解的配置类
		this.reader = new AnnotatedBeanDefinitionReader(this);
		// spring提供api来动态扫描注解
		// 一般供拓展spring的时候用的,内部Spring并不使用这个对象
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

这个构造方法中做了一下的事情:

  • 1.注册内置BeanPostProcessor
  • 2.注册相关的BeanDefinition

我们来看看AnnotatedBeanDefinitionReader的构造方法到底做了什么:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
	}

我们再跟进去:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

继续跟进到registerAnnotationConfigProcessors方法:

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
		registerAnnotationConfigProcessors(registry, null);
	}

好吧。再进最后一次:

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		.......................

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		.......................
	}

这个方法太长了,我们简单看中间一段就好。

1、这里首先会判断容器中是否已经注册了ConfigurationClassPostProcessor Bean。

2、如果不存在(当然这里肯定是不存在的),就通过RootBeanDefinition的构造方法获得ConfigurationClassPostProcessor的BeanDefinition,RootBeanDefinition是BeanDefinition的子类。

3、执行registerPostProcessor方法,registerPostProcessor方法内部就是注册Bean,当然这里注册其他Bean也是一样的流程。


三、BeanDefinition定义

BeanDefinition是用来描述Bean的,里面存放着关于Bean的一系列信息,比如Bean的作用域,Bean所对应的Class,是否懒加载,是否Primary等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值