美文网首页
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