美文网首页
spring-源码02-IOC加载流程

spring-源码02-IOC加载流程

作者: Coding626 | 来源:发表于2020-10-30 17:04 被阅读0次

    IOC角色

    ioc是spring中最最最最核心的内容,之所以打这么多最,是因为ioc是spring的底层支撑组件,后面讲述的
    AOP、事务、和其他框架集成spring均是基于ioc去实现的。

    IOC是什么

    IOC-全拼Inversion of Control,翻译过来叫控制反转。在没有IOC的情况下,我们创建对象是需要手动去
    new对象,解耦比较复杂,IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间
    的解耦,IOC实现了以下三点:
      1.资源不由使用资源的双方管理,而由不使用资源的第三方管理
      2.资源集中管理,实现资源的可配置和易管理
      3.降低了使用资源双方的依赖程度-耦合度

    IOC加载流程

    那么IOC到底是怎么实现的?大概分为以下几个主流程,主流程中一些比较重要的流程会在后面给出,本节
    只讲主流程,干货开始。

    1.xml、注解配置bean

    文章源码以注解方式为例,如@Bean、@Component

    2.ClassPathXmlApplicationContext和AnnotationConfigContext加载1配置

    (1)以注解AnnotationConfigContext为例,这个类作为源码阅读的总入口,首先初始化context,初始化父类beanFactory image.png
    
    public class ApplicationStart {
        
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MainConfig.class);
            Car bean = (Car)context.getBean("car");
            System.out.println(bean.getName());
        }
    }
    
    

    Mainconfig代码

    @Configuration
    @ComponentScan(basePackages = {"com.wubanf.friends.test.spring"})
    @EnableTransactionManagement
    public class MainConfig {
    
    }
    

    我们来看看AnnotationConfigApplicationContext的构造方法,这里有三个核心的大方法:

    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
            
            this();
            //注册配置类
            register(annotatedClasses);
            //IOC容器刷新
            refresh();
        }
    

    1.其中this会初始化化两个类,分别是AnnotatedBeanDefinitionReader-注解模式下bean定义扫描器和ClassPathBeanDefinitionScanner-classPath类型的bean定义扫描器,这里会初始化很多spring内置bean后置处理器(后置处理器的作用将在后面章节给出),spring体系中,实例化bean是需要先将bean转成bean定义,然后才能交给bean工厂实例化,bean定义就好比是工厂的加工原材料。

    2.register会加载我们的配置类,如我上面自己定义的MainConfig类,通过自定义配置扫描的包,会自动扫描该包的bean,并且装载成bean定义,放入beanDefinitionMap中,后面供bean工厂使用

       BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
       definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
       BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    

    3.refresh-ioc容器刷新接口,真正实例化的步骤均在里面

    3.refresh()--ioc容器刷新

    这个是ioc实例化bean的核心方法入口,代码如下,其中核心是invokeBeanFactoryPostProcessors、registerBeanPostProcessors、finishBeanFactoryInitialization这三个方法

    
                prepareRefresh();
    
                
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                
                prepareBeanFactory(beanFactory);
    
                try {
                    
                    postProcessBeanFactory(beanFactory);
    
                    // 调用我们的bean工厂的后置处理器.
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // 调用我们bean的后置处理器
                    registerBeanPostProcessors(beanFactory);
    
                    
                    initMessageSource();
    
                
                    initApplicationEventMulticaster();
    
                    
                    onRefresh();
    
                    
                    registerListeners();
    
                    //实例化bean.
                    finishBeanFactoryInitialization(beanFactory);
    
                    
                    finishRefresh();
    

    4.finishBeanFactoryInitialization-实例化我们剩余的单实例bean

    实例化bean,这里主要分为三个步骤,方法入口beanFactory.getBean->AbstractBeanFactory.doGetBean->createBean->doCreateBean
    1.反射实例化对象,createInstance
    2.填充属性,populate @Autowired,@Value
    3.初始化方法,initializeBean

    总结

    该节讲述了spring加载bean的大体流程,配置->初始化beanDefinitionReader->实例化spring内置后置处理器->加载配置类->加载bean定义->bean工程实例化bean。
    初次阅读源码的时候忌一头栽进源码debug,spring的源码调用链很复杂,很容易迷失方向,先了解原理和主体流程会事半功倍,后面的流程细节慢慢发

    相关文章

      网友评论

          本文标题:spring-源码02-IOC加载流程

          本文链接:https://www.haomeiwen.com/subject/yledvktx.html