Ioc容器加载过程-bean生命周期源码解析

Spring IOC容器的加载过程

1、实例化容器:AnnotationConfigApplicationContext

首先从这里出发:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);

创建 AnnotationConfigApplicationContext对象实例化bean工厂,走的是无参构造方法,而无参构造方法又会去调用父类的无参构造方法。为什么这里要实现的是DefaultListableBeanFactory()?因为这个类继承了最多的父类,包括BeanDefinitionRegistry,功能是最丰富的,比如注册bean定义的方法。所以实现了这个DefaultListableBeanFactory()后赋值给beanFactory,得到了bean工厂

//根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少
 public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
 //调用无参构造函数,会先调用父类GenericApplicationContext的构造函数
 //父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory
 //本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefi
nitionScanner scanner
 //scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
 this();
 //把传入的类进行注册,这里有两个情况,
 //传入传统的配置类
 //传入bean(虽然一般没有人会这么做
 //看到后面会知道spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配
置类
 //但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean
 register(annotatedClasses);
 //刷新
 refresh();
 }
//this()执行的无参构造方法
public AnnotationConfigApplicationContext() {
		/**
		 * 初始化注解模式下的bean定义扫描器
		 * 调用AnnotatedBeanDefinitionReader构造方法,传入的是this(AnnotationConfigApplicationContext)对象
		 */

		this.reader = new AnnotatedBeanDefinitionReader(this);
		/**
		 * 初始化我们的classPath类型的bean定义扫描器
		 */
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

//父类具体执行的构造方法
public GenericApplicationContext() {
		/**
		 * 调用父类的构造函数,为ApplicationContext spring上下文对象初始beanFactory
		 * 为啥是DefaultListableBeanFactory?我们去看BeanFactory接口的时候
		 * 发DefaultListableBeanFactory是最底层的实现,功能是最全的
		 */
		this.beanFactory = new DefaultListableBeanFactory();
	}

接下来会去执行new  AnnotatedBeanDefinitionReader(this)(创建用去读取配置类的工具。);在执行这一句的时候会去注册一些创世纪的类例的bean定义如ConfigurationClassPostProcessor.class(在这个类中负责解析配置类,会解析加了@Configuration\@Component\@Import等注解)、AutowiredAnnotationBeanPostProcessor.class(这个类会去解析@Autowired)等处理器,这个只是注册这些类,真正去把类解析bean定义的是由他注册的后置处理器去完成的。

接下来会去执行this.scanner = new ClassPathBeanDefinitionScanner(this);创建扫面读取到的配置类的工具。在这个扫描工具里面有个doScan(String basePackages)方法,提供一个手动传入扫描包进行扫描的支持。传入一个包路径,通过这个路径扫描到包里面的所有类。

在构造方法跳出来之后会执行注册配置类到bean定义里面

 接着会执行refresh()方法

 refresh()方法

invokeBeanFactoryPostProcessors(beanFactory);

调用我们的bean工厂的后置处理器。因为之前已经注册了创世纪类ConfigurationClassPostProcessor.class,所以这里执行getBean()就会实例化注册了的创世纪的类(实现了postprocessor接口),这里调用这些实例化了的处理器就会去解析配置类、@CompenetScan、@Import等注解注册到bean定义里面。

registerBeanPostProcessors(beanFactory);

注册bean的后置处理器

finishBeanFactoryInitialization(beanFactory);

实例化剩余的单例bean。

在这里面会执行getBean(),判断需要实例化的这个Bean定义是否符合生产标准、是不是factorybean。符合标准了才会执行getBean()。这时候会先去判断一级缓存是否有,如果拿到了直接返回,如果没有拿到就会标记为isInCreation正在创建,去执行creatBean()

creatBean()中会执行第一个bean后置处理器,这里可以阻止bean的创建交由用户自己创建。

接着就来到了doCreatBean(),进行实例化、填充属性、初始化,最终把bean放入一级缓存。

springBean生命周期

阶段1:处理名字,检查缓存,因为spring是支持别名系统,也就是一个bean可以起一个小名,将来根据小名也能找到这个bean,所以在这一步是将这个别名翻译成真正的名字。是为了实现单例bean,检查缓存单例池中是否已经存在,如果有就直接拿不再创建。

阶段2:检查父工厂,针对的是beanFactory有一个父子继承关系,如果子工厂没有这个Bean就会去父工厂中走getBean

阶段3:检查bean的dependsOn,应该先创建dependon的bean,保证先后顺序

阶段4:按Scope创建bean

  • 创建singleton
  • 创建prototype:多例bean
  • 创建其他scope

阶段5:

  • 创建bean实例
  • 依赖注入
  • 初始化:调用各种初始化方法。
  • 登记可销毁bean

阶段6:类型转换:根据requiredType进行类型转换。

阶段7:销毁阶段5登记的可销毁bean

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值