深入解析spring源码IOC流程
Posted java软件技术
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入解析spring源码IOC流程相关的知识,希望对你有一定的参考价值。
一、初始化上下文对象。
1、执行第一行this()调用无参构造函数。
1.1、this()无参构造函数默认先执行super()调用父类GenericApplicationContext的无参构造器,目的在于生成一个DefaultListableBeanFactory IOC容器,主要是存放bean定义信息。
1.1.1、上下文类 AnnotationConfigApplicationCon text的继承关系图。
1.2、super()调完父类构造后,返回this()方法里执行this.reader = new AnnotatedBeanDefinitionReader (this);先通过getOrCreateEnvironment(registry)创建系统环境信息。
2、This()执行完后执行this.scan(basePackages);注册配置类。
2.1、将配置类bean定义信息到beanDefinitionMap容器中。
3、this.refresh();这个方法是spring最重要的一个方法,进行一些后置处理器、广播器、监听器、国际化、实例化bean的过程。
3.1、this.prepareRefresh();刷新前预处理操作,记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写。
3.1.1、this.startupDate = System.current
TimeMillis();记录容器启动时间
//设置容器的当前状态
this.closed.set(false);
this.active.set(true);
//初始化属性,留给子类覆盖实现
nitPropertySources();
//验证必要属性是否都已经被解析
getEnvironment().validateRequire
dProperties();
// 新建一个LinkedHashSet目的为了保存
容器中一些事件。
this.earlyApplicationEvents = new
LinkedHashSet<>();
3.2、ConfigurableListableBeanFactory beanFacto ry = this.obtainFreshBeanFactory();this.refreshBe anFactory();初始化beanFactory,设置序列化Id,并执行加载和解析配置操作。
3.2.1、return this.getBeanFactory();返回beanFactory实例。
3.3、this.prepareBeanFactory(beanFactory);对beanFactry 做了一些准备工作,设置了一些属性来扩展功能。
3.4、this.postProcessBeanFactory(beanFactory);子类覆盖方法做额外的处理。这里并没有实际实现,供子类实现。
3.5、this.invokeBeanFactoryPostProcessors(b eanFactory);激活各种BeanFactory 后置处理器(调用了各种BeanFactoryPostProcessor)。其中最为关键的是 ConfigurationClassPostProcessor ,在这里完成了配置类的解析。
3.6、this.registerBeanPostProcessors(beanFa ctory);注册拦截bean创建的bean后置处理器,这里仅仅是注册,真正调用是在getBean。
3.7、this.initMessageSource();初始化Message Source组件(做国际化功能;消息绑定,消息解析)。
3.8、this.initApplicationEventMulticaster();为这个context初始化一个事件广播器(ApplicationEvent Multicaste);如果用户自定义了事件广播器,在使用用户自定义的事件广播器,如果用户没有自定义事件广播器,则使用默认的 ApplicationEventMulticas ter。
3.9、this.onRefresh();子类重写这个方法,在容器刷新的时候可以自定义逻辑;在AbstractApplication Context的子类中初始化其他特殊的bean。其实就是初始化ThemeSource接口的实例。这个方法需要在所有单例bean初始化之前调用。
3.10、this.registerListeners();就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到上下文的ApplicationEventMulticaster中。
3.11、this.finishBeanFactoryInitialization(beanFact ory);完成单例、非懒加载、非抽象bean的创建及初始化。
3.11.1、beanFactory.preInstantiateSingletons();实例化、初始化单例Bean。
3.11.2、this.getBean(beanName)。
3.11.3、return this.doGetBean(name, (Class)null, (Object[])null, false); Object sharedInstance = this.getSingleton(beanName);这里先尝试从缓存中获取,获取不到再走后面创建的流程,获取到有两种情况,一种是Bean创建完成存储到最终singletonOb jects一级缓存中。另一种是未创建完成半成品工厂对象,但先预存到一个单独的二级singletonFacto ries缓存中,这种是针对可能存在循环引用的情况的处理。如果在二级缓存中,会把半成品工厂对象取出对象放在三级缓存,然后从二级缓存中移除。
3.11.4、判断如果是原型多例对象会报异常。
3.11.5、进行已创建标记
3.11.6、// 根据名字获取合并过的对应的RootBean
Definition
RootBeanDefinition mbd = getMergedLoca
lBeanDefinition(beanName);
// 检查mbd是否为抽象的或mbd为单例,但
存 在args的情况(args只有初始化
原型对象才允许存在)
checkMergedBeanDefinition(mbd,
beanName, args);
3.11.7、开始创建单例对象。
3.11.8、beanInstance = this.doCreateBean(bean Name, mbdToUse, args);创建bean。
3.11.9、BeanWrapper ,包含了真正的bean对象和bean的class,以及PropertyDescriptor集合,单例的情况下尝试从factoryBeanInstanceCache获取 insta nceWrapper ,并从缓存移除instanceWrapper = this.factoryBeanInstanceCache.remove(beanNa me)。
3.11.10、instanceWrapper = this.createBeanInstan ce(beanName, mbd, args);如果 instanceWrapper 为空,那就 创建对应的beanInstance。获取beanclass,首先确保bean 已经被解析过,如果beanclass为空,且beanclass不是public 且没有权限访问构造函数和方法则抛出异常。
Supplier类似于factoryBean,然后从Supplier.get()的bean,并把bean包装成BeanWrapper,然后初始化BeanWrapper ;Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
//如果存在对应的工厂方法,那么就使用工厂方法
进行初始化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(bea
nName, mbd, args);
}
//一个类有多个构造函数,判断是否有解析过构造
函数或者factoryMethod
if (mbd.resolvedConstructorOrFactoryMethod
!= null) {
// 设置 已经解析
resolved = true;
如果autowireNecessary为true说明是采用构造
函数注入
autowireNecessary = mbd.constructorArgum
entsResolved;
}
3.11.11、this.instantiateBean(beanName, mbd),使用无参构造函数创建对象
3.11.12、通过反射实体化对象。
3.11.13、BeanWrapper instanceWrapper创建之后,往下执行应MergedBeanDefinition PostProcessor 后处理器,合并bean的定义信息@PostConstruct,@A utowire,@Value,@ Resource,@PreDestory等等注解信息就是在这一步完成预解析,并且将注解需要的信息放入缓存。
3.11.14、是否需要提前曝光=单例&允许循环依赖&bean正在创建中。如果当前bean是单例,且支持循环依赖,且当前bean正在创建,通过往singletonFa ctories添加一个objectFactory,这样后期如果有其他bean依赖该bean 可以从singletonFactories获取到bean,getEarlyBeanReference可以对返回的bean进行修改,这边目前除了可能会返回动态代理对象 其他的都是直接返回bean。
3.11.15、对bean属性进行填充,注入bean中的属性,会递归初始化依赖的bean调用初始化方法,比如init-method、注入Aware对象、应用后处理器。
3.11.16、检测循环依赖。
3.11.17、注册DisposableBean。如果配置了destroy-method,这里需要注册,以便在销毁时调用。
3.12、这是在bean的实例化,初始化完成后的一些操作,例如生命周期变更的回调,发布applicationContext刷新完成的广播等。
...end....
以上是关于深入解析spring源码IOC流程的主要内容,如果未能解决你的问题,请参考以下文章