vlambda博客
学习文章列表

深入解析spring源码IOC流程

        Spring 被称为 J2EE 的春天,是一个开源的轻量级的 Java 开发框架, 具有 控制反转 (IOC)和 面向切面 (AOP)两大核心。Spring 框架不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。

源码入口(注解方式)

一、初始化上下文对象。

深入解析spring源码IOC流程 1、执行第一行this()调用无参构造函数。

深入解析spring源码IOC流程

1.1、this()无参构造函数默认先执行super()调用父类GenericApplicationContext的无参构造器,目的在于生成一个DefaultListableBeanFactory IOC容器,主要是存放bean定义信息。

深入解析spring源码IOC流程

1.1.1、上下文类 AnnotationConfigApplicationCon text的继承关系图。

深入解析spring源码IOC流程

1.2、super()调完父类构造后,返回this()方法里执行this.reader = new AnnotatedBeanDefinitionReader (this);先通过getOrCreateEnvironment(registry)创建系统环境信息。

深入解析spring源码IOC流程

1.3、(1)this.conditionEvaluator = new ConditionE valuator(registry, environment,   null);创建一个条件计算器对象 ,用于处理 条件表达式 @Conditio nl注解。
      (2)AnnotationConfigUtils. registerAnnotati onConfigProcessors (this.registry);为容器中注册系统的bean定义信息 ,这些后置处理器是Spring初始化内部beandefinition的容器,没有这个就没有IOC,非常重要。

深入解析spring源码IOC流程

1.4、ClassPathBeanDefinitionScanner就是用来扫描我们classpath下的标注了@Service @Compent @Respository @Controller注解。

深入解析spring源码IOC流程

2、This()执行完后执行this.scan(basePackages);注册配置类。深入解析spring源码IOC流程

深入解析spring源码IOC流程

2.1、将配置类bean定义信息到beanDefinitionMap容器中。

深入解析spring源码IOC流程

3、this.refresh();这个方法是spring最重要的一个方法,进行一些后置处理器、广播器、监听器、国际化、实例化bean的过程。

深入解析spring源码IOC流程

3.1、this.prepareRefresh();刷新前预处理操作,记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写。

深入解析spring源码IOC流程

3.1.1this.startupDate = System.current 

            TimeMillis();记录容器启动时间

            //设置容器的当前状态

            this.closed.set(false);

            this.active.set(true);

            //初始化属性,留给子类覆盖实现

            nitPropertySources();

            //验证必要属性是否都已经被解析

            getEnvironment().validateRequire

            dProperties();

            // 新建一个LinkedHashSet目的为了保存

            容器中一些事件。

            this.earlyApplicationEvents = new 

            LinkedHashSet<>();

深入解析spring源码IOC流程

3.2、ConfigurableListableBeanFactory beanFacto ry = this.obtainFreshBeanFactory();this.refreshBe anFactory();初始化beanFactory,设置序列化Id,并执行加载和解析配置操作。

深入解析spring源码IOC流程

3.2.1、return this.getBeanFactory();返回beanFactory实例。

深入解析spring源码IOC流程

深入解析spring源码IOC流程

深入解析spring源码IOC流程

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中。

深入解析spring源码IOC流程

3.11、this.finishBeanFactoryInitialization(beanFact ory);完成单例、非懒加载、非抽象bean的创建及初始化。

深入解析spring源码IOC流程

深入解析spring源码IOC流程

3.11.1、beanFactory.preInstantiateSingletons();实例化、初始化单例Bean。


深入解析spring源码IOC流程

3.11.2、this.getBean(beanName)。

深入解析spring源码IOC流程

深入解析spring源码IOC流程

3.11.3、return this.doGetBean(name, (Class)null, (Object[])null, false); Object sharedInstance = this.getSingleton(beanName);这里先尝试从缓存中获取,获取不到再走后面创建的流程,获取到有两种情况,一种是Bean创建完成存储到最终singletonOb jects一级缓存中。另一种是未创建完成半成品工厂对象,但先预存到一个单独的二级singletonFacto ries缓存中,这种是针对可能存在循环引用的情况的处理。如果在二级缓存中,会把半成品工厂对象取出对象放在三级缓存,然后从二级缓存中移除。

深入解析spring源码IOC流程

3.11.4、判断如果是原型多例对象会报异常。

深入解析spring源码IOC流程

3.11.5、进行已创建标记

3.11.6、// 根据名字获取合并过的对应的RootBean

             Definition

             RootBeanDefinition mbd = getMergedLoca

             lBeanDefinition(beanName);

             // 检查mbd是否为抽象的或mbd为单例,但

             存 在args的情况(args只有初始化

             原型对象才允许存在)

             checkMergedBeanDefinition(mbd,

             beanName, args);

深入解析spring源码IOC流程

3.11.7、开始创建单例对象。

深入解析spring源码IOC流程

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)。

深入解析spring源码IOC流程

3.11.10、instanceWrapper = this.createBeanInstan ce(beanName, mbd, args);如果 instanceWrapper 为空,那就 创建对应的beanInstance。获取beanclass,首先确保bean 已经被解析过,如果beanclass为空,且beanclass不是public 且没有权限访问构造函数和方法则抛出异常。

深入解析spring源码IOC流程

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;

        }

深入解析spring源码IOC流程

深入解析spring源码IOC流程

深入解析spring源码IOC流程

3.11.11、this.instantiateBean(beanName, mbd),使用无参构造函数创建对象     

深入解析spring源码IOC流程

3.11.12、通过反射实体化对象。

深入解析spring源码IOC流程

3.11.13、BeanWrapper instanceWrapper创建之后,往下执行应MergedBeanDefinition PostProcessor 后处理器,合并bean的定义信息@PostConstruct,@A utowire,@Value,@ Resource,@PreDestory等等注解信息就是在这一步完成预解析,并且将注解需要的信息放入缓存。

深入解析spring源码IOC流程

3.11.14、是否需要提前曝光=单例&允许循环依赖&bean正在创建中。如果当前bean是单例,且支持循环依赖,且当前bean正在创建,通过往singletonFa ctories添加一个objectFactory,这样后期如果有其他bean依赖该bean 可以从singletonFactories获取到bean,getEarlyBeanReference可以对返回的bean进行修改,这边目前除了可能会返回动态代理对象 其他的都是直接返回bean。

深入解析spring源码IOC流程

3.11.15、对bean属性进行填充,注入bean中的属性,会递归初始化依赖的bean调用初始化方法,比如init-method、注入Aware对象、应用后处理器。

深入解析spring源码IOC流程

3.11.16、检测循环依赖。

3.11.17、注册DisposableBean。如果配置了destroy-method,这里需要注册,以便在销毁时调用。

3.12、这是在bean的实例化,初始化完成后的一些操作,例如生命周期变更的回调,发布applicationContext刷新完成的广播等。


...end....