spring IOC源码解析


前言

spring 是当前最广泛使用的开源框架,而spring framework 则是spring全家桶的基础。spring framework最重要的是 IOC 和 AOP。其中 IOC 又是Spring framework 的基础。
今天我们要做的就是解析IOC,总的来说IOC有两点至关重要:1、创建bean容器;2、初始化bean。

源码分析

本文以JAVA_CONFIG(注解)来解读spring IOC 源码。

下面我们从一段简单的代码出发分析

配置类

@Configuration
@ComponentScan("com.zhouxh")
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = 
                new AnnotationConfigApplicationContext(Main.class);
        TestService testService = (TestService)applicationContext.getBean("testService");
        testService.sayHi();
        System.out.println("结束");
    }
}

service类

package com.zhouxh.service;
import org.springframework.stereotype.Service;

@Service("testService")
public class TestService {
    public void sayHi(){
        System.out.println("hello spring");
    }
}

通过注解@Configuration将Main类标记为配置类,并通过@ComponentScan("com.zhouxh")指定bean扫描路径。

Spring IoC容器的加载过程

脑图


1.实例化容器 AnnotationConfigApplicationContext

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Main.class);

该有参构造的简单说明:

  • 可以接收多个配置类,不过一般情况下,只会传入一个配置类
  • 这个配置类有两种情况,一种是传统意义上的带上@Configuration注解的配置类,还有一种是没有带上@Configuration,但是带有@Component@Import@ImportResouce@Service@ComponentScan等注解的配置类,在Spring内部把前者称为Full配置类,把后者称之为Lite配置类。在本源码分析中,有些地方也把Lite配置类称为普通Bean。
    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
      // 调用无参构造函数
      this();
      // 注册配置类
      register(componentClasses);
      // IOC 容器刷新接口
      refresh();
    }
    

    this()

在通过this()方法调用无参构造函数时,会隐式的调用父类的构造函数

public AnnotationConfigApplicationContext() {
    // 执行父类无参构造,设置bean工厂类
    /**
     *  public GenericApplicationContext() {
     *      this.beanFactory = new DefaultListableBeanFactory();
     *  }
     */
    // 设置读取配置类
    this.reader = new AnnotatedBeanDefinitionReader(this);
    // 设置扫描类,默认情况下没有使用,除非外部显示的调用scan()方法指定扫描路径
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

AnnotatedBeanDefinitionReader【beanDefinition读取器】
主要做了2件事情

  1. 注册内置BeanPostProcessor
  2. 注册相关的BeanDefinition
    通过对new AnnotatedBeanDefinitionReader(this)代码的追踪发现真正做事情的AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);由于该方法代码较多,这里只把最核心的代码贴出来。
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
     RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
     def.setSource(source);
     beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    
    在该方法中存在较多的类似的代码。其主要目的就是为了给容器添加内置组件
  3. 判断容器中是否已经存在了ConfigurationClassPostProcessor Bean
  4. 如果不存在(第一次运行必然不存在),就通过RootBeanDefinition的构造方法获得ConfigurationClassPostProcessor的BeanDefinition,RootBeanDefinition是BeanDefinition的子类
  5. 执行registerPostProcessor方法,registerPostProcessor方法内部就是注册Bean,当然这里注册其他Bean也是一样的流程。

该方法最终会将ContextAnnotationAutowireCandidateResolver,ConfigurationClassPostProcessor【bean的扫描和注册】,CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor【@Autowired属性的自动注入】,PersistenceAnnotationBeanPostProcessor 这5个组件添加到spring容器中。

register(componentClasses);

register 是将传入的配置类解析成beanDefinition,并注册到容器中。

  1. 包装成 BeanDefinition

  2. 判断条件是否满足 @condition

  3. 设置bean作用域

  4. 解析通用注解(@Lazy、@Primary、@DependsOn、@Role、@Description),并将属性设置到beanDefinition中

  5. 将beanDefinition注册到容器中

    private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
         @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
         @Nullable BeanDefinitionCustomizer[] customizers) {
    
     // 将beanClass 包装成 BeanDefinition
     AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
         //判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析
     if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
         return;
     }
     abd.setInstanceSupplier(supplier);
     // 设置bean作用域 spring 默认 singleton
     ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
     abd.setScope(scopeMetadata.getScopeName());
     String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
     // 解析通用注解(@Lazy、@Primary、@DependsOn、@Role、@Description),并将属性设置到beanDefinition中
     AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
     if (qualifiers != null) {
         for (Class<? extends Annotation> qualifier : qualifiers) {
             if (Primary.class == qualifier) {
                 abd.setPrimary(true);
             }
             else if (Lazy.class == qualifier) {
                 abd.setLazyInit(true);
             }
             else {
                 abd.addQualifier(new AutowireCandidateQualifier(qualifier));
             }
         }
     }
     if (customizers != null) {
         for (BeanDefinitionCustomizer customizer : customizers) {
             customizer.customize(abd);
         }
     }
     BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
     definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
     // 将beanDefinition 添加到map缓存中
     BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
    

    refresh();

    到这里为止,我们想要注入的testService类还没有被扫描,在上面的方法中只注册了默认的内置bean和配置类。

真正的重点代码在这个refresh()刷新方法中。

脑图

prepareRefresh();

开始刷新方法的准备工作,主要记录容器开始时间、启动标识之类的
需要注意的只有两行代码

//初始化属性,由字类覆盖实现
initPropertySources();
// 验证必要属性是否都已经被解析
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();

initPropertySources方法,我们可以继承该类并重写该方法,通过然后给Environment中添加某参数。

protected void initPropertySources() {
    System.out.println("扩展initPropertySource");
    //这里添加了一个username属性到Environment里面,以方便我们在后面用到
    getEnvironment().getSystemProperties().put("username","bobo");
    //这里要求Environment中必须包含username属性,如果不包含,则抛出异常
    // 在这里设置会被getEnvironment().validateRequiredProperties();检验到。
    getEnvironment().setRequiredProperties("username");
}     

prepareBeanFactory(beanFactory)

给beanFactory添加必要的组件
需要关注的代码

// BeanFactory接口未在普通工厂中注册为可解析类型。 MessageSource注册为Bean(并发现用于自动装配)。
// 意味着以下4各类可以在任意组件中自动装配,第一个参数是自动装配的类型,第二个字段是自动装配的值
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

//添加一个后置处理器:ApplicationListenerDetector,此后置处理器实现了BeanPostProcessor接口
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

postProcessBeanFactory(beanFactory)

spring提供的拓展点,以便子类继承后对beanFactory进行个性化设置。

invokeBeanFactoryPostProcessors(beanFactory)

需关注如下代码:

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, 
        List<BeanFactoryPostProcessor> beanFactoryPostProcessors) 

参数里的 beanFactoryPostProcessors 不是spring管理的 beanFactoryPostProcessor 而是从外部通过如下代码添加的,如果没有通过该方法添加 默认为空

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.addBeanFactoryPostProcessor(xxx);

invokeBeanFactoryPostProcessors方法中存在三段类似的代码,此处只粘贴一段进行分析

这三段相似代码意味着:BeanFactoryPostProcessor按照代码先后顺序依次执行

  1. 首先执行实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors。bean定义后置注册处理器
  2. 然后执行实现Ordered接口的BeanDefinitionRegistryPostProcessors。
  3. 最后执行普通的bean定义注册后置处理器
    String[] postProcessorNames =
         beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
     if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
         processedBeans.add(ppName);
     }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
    
    invokeBeanDefinitionRegistryPostProcessors
    以上代码大致逻辑为:选择出对应类型的BeanFactoryPostProcessor,然后通过invokeBeanDefinitionRegistryPostProcessors方法扫描出需要注册的bean,并加入到注册表中。

调用invokeBeanDefinitionRegistryPostProcessors方法最终是调用processConfigBeanDefinitions方法

该方法大致做以下几件事:

  1. 扫描已经注册的bean中被@Configuration修饰的配置类,获取他的扫描路径

  2. 将配置类排序

  3. 通过扫描路径,扫描路径下所有被@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean修饰的类和方法,并添加到对应的集合中。

  4. 从集合中去除beanDefinition 并注册。

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
     List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
     // 这里就是需要注册的所有bean 的 name
     String[] candidateNames = registry.getBeanDefinitionNames();
     // 循环选择出需要注册bean中的配置类 @Configuration 
     for (String beanName : candidateNames) {
         BeanDefinition beanDef = registry.getBeanDefinition(beanName);
         if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
             }
         }
         else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
             configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
         }
     }
    
     // Return immediately if no @Configuration classes were found
     if (configCandidates.isEmpty()) {
         return;
     }
    
     // 根据 @Order注解的排序 ,排位靠前的先注册
     configCandidates.sort((bd1, bd2) -> {
         int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
         int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
         return Integer.compare(i1, i2);
     });
    
     // Detect any custom bean name generation strategy supplied through the enclosing application context
     SingletonBeanRegistry sbr = null;
     // 如果是单例的
     if (registry instanceof SingletonBeanRegistry) {
         sbr = (SingletonBeanRegistry) registry;
         if (!this.localBeanNameGeneratorSet) {
             BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                     AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
             if (generator != null) {
                 this.componentScanBeanNameGenerator = generator;
                 this.importBeanNameGenerator = generator;
             }
         }
     }
    
     if (this.environment == null) {
         this.environment = new StandardEnvironment();
     }
     
     ConfigurationClassParser parser = new ConfigurationClassParser(
             this.metadataReaderFactory, this.problemReporter, this.environment,
             this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
     Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
     Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
     do {
         // 解析配置类,解析扫描路径下被@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean修饰的类和方法,并添加到对应的集合中。
         parser.parse(candidates);
         parser.validate();
    
         Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
         configClasses.removeAll(alreadyParsed);
    
         // Read the model and create bean definitions based on its content
         if (this.reader == null) {
             this.reader = new ConfigurationClassBeanDefinitionReader(
                     registry, this.sourceExtractor, this.resourceLoader, this.environment,
                     this.importBeanNameGenerator, parser.getImportRegistry());
         }
                 // 从对应的集合中取出将beanDefinition注册
         this.reader.loadBeanDefinitions(configClasses);
         alreadyParsed.addAll(configClasses);
    
         candidates.clear();
         // 判断是否有新的bean注册,有就注册 
         if (registry.getBeanDefinitionCount() > candidateNames.length) {
             String[] newCandidateNames = registry.getBeanDefinitionNames();
             Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
             Set<String> alreadyParsedClasses = new HashSet<>();
             for (ConfigurationClass configurationClass : alreadyParsed) {
                 alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
             }
             for (String candidateName : newCandidateNames) {
                 if (!oldCandidateNames.contains(candidateName)) {
                     BeanDefinition bd = registry.getBeanDefinition(candidateName);
                     if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                             !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                         candidates.add(new BeanDefinitionHolder(bd, candidateName));
                     }
                 }
             }
             candidateNames = newCandidateNames;
         }
     }
     while (!candidates.isEmpty());
    
     // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
     if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
         sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
     }
    
     if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
         // Clear cache in externally provided MetadataReaderFactory; this is a no-op
         // for a shared cache since it'll be cleared by the ApplicationContext.
         ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
     }
    }
    

    registerBeanPostProcessors(beanFactory)

    实例化和注册beanFactory中扩展了BeanPostProcessor的bean。
    例如:
    AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)
    RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)
    CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等

initMessageSource()【非IOC主线代码】

初始化国际化资源处理器

initApplicationEventMulticaster()

初始化创建事件多播器。

registerListeners()

注册监听器

以上两个方法【initApplicationEventMulticaster/registerListeners】和spring的事件监听机制密切相关。

onRefresh()

spring提供的拓展点,在springboot中有被使用

finishBeanFactoryInitialization()

完成上下文的bean工厂的初始化,初始化所有剩余的单例bean。
需要关注的核心代码

  1. 将所有beanDefinition设置为不可变,避免在实例化时,bean定义发生改变

  2. 实例化所有单例bean

    // 将所有beanDefinition设置为不可变,避免在实例化时,bean定义发生改变
    beanFactory.freezeConfiguration();
    // 实例化所有单例bean
    beanFactory.preInstantiateSingletons();
    
    DefaultListableBeanFactory.preInstantiateSingletons()
  3. 获取之前保存在beanDefinitionNames中的所有的beanName

  4. 循环bean,获取作用域为单例的bean

  5. 判断是否是factoryBean类型【bean继承FactoryBean,通过重写getObject(),自定义传入bean】

  6. 非factoryBean,通过getBean实例化,并将bean实例保存在容器(DefaultSingletonBeanRegistry.singletonObjects)中

  7. 调用所有实例化完成的bean的回调方法

    public void preInstantiateSingletons() throws BeansException {
     if (logger.isTraceEnabled()) {
         logger.trace("Pre-instantiating singletons in " + this);
     }
    
     // 获取之前保存在beanDefinitionNames中的beanName
     List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
     // 循环bean,获取单例bean
     for (String beanName : beanNames) {
         RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
         if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
             // 判断是否是factoryBean
             if (isFactoryBean(beanName)) {
                 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                 if (bean instanceof FactoryBean) {
                     FactoryBean<?> factory = (FactoryBean<?>) bean;
                     boolean isEagerInit;
                     if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                         isEagerInit = AccessController.doPrivileged(
                                 (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                                 getAccessControlContext());
                     }
                     else {
                         isEagerInit = (factory instanceof SmartFactoryBean &&
                                 ((SmartFactoryBean<?>) factory).isEagerInit());
                     }
                     if (isEagerInit) {
                         getBean(beanName);
                     }
                 }
             }
             else {
                 // 没有继承FacetoryBean的bean,通过getBean实例化
                 getBean(beanName);
             }
         }
     }
    
     // 触发所有实例化bean的回调方法
     for (String beanName : beanNames) {
         Object singletonInstance = getSingleton(beanName);
         if (singletonInstance instanceof SmartInitializingSingleton) {
             SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
             if (System.getSecurityManager() != null) {
                 AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                     smartSingleton.afterSingletonsInstantiated();
                     return null;
                 }, getAccessControlContext());
             }
             else {
                 smartSingleton.afterSingletonsInstantiated();
             }
         }
     }
    }
    

    finishRefresh()

    发布相应的事件

  8. 清除上下文资源缓存(如扫描中的ASM元数据)

  9. 初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)。

  10. 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作

    protected void finishRefresh() {
     // 清除上下文的资源缓存(例如来自扫描的ASM元数据)。
     clearResourceCaches();
    
     // 初始化生命周期处理器
     initLifecycleProcessor();
    
     // 首先将刷新传播到生命周期处理器。
     getLifecycleProcessor().onRefresh();
    
     // 推送上下文刷新完毕事件到相应的监听器
     publishEvent(new ContextRefreshedEvent(this));
    
     // Participate in LiveBeansView MBean, if active.
     LiveBeansView.registerApplicationContext(this);
    }
    

    总结

    至此Spring IOC 初始化和spring bean加载过程就结束.

Spring IOC 初始化: 创建beanFactory实例对象,创建BeanDefinitionReader,创建BeanDefinitionScanner,将ContextAnnotationAutowireCandidateResolver,ConfigurationClassPostProcessor【bean的扫描和注册】,CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor【@Autowired属性的自动注入】,PersistenceAnnotationBeanPostProcessor 这5个组件添加到spring容器中。

spring bean加载过程:

  • 通过BeanDefinitionReader将bean配置类从java_config中读取出来
  • 再由ConfigurationClassPostProcessor解析配置类
  • 通过BeanDefinitionScanner扫描配置类中的配置的扫描路径
  • ConfigurationClassPostProcessor包装成beanDefinition,注册到(put)beanDefinitionMap中。
  • 最后通过beanFactorygetBean方法将bean实例化.
    • 在这过程中会调用registerBeanPostProcessors方法注册的后置处理器,对bean进行数据填充
    • AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)
      RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)
      CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等


文章作者: zhouxh-z
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 zhouxh-z !
 上一篇
spring怎么解决循环依赖? spring怎么解决循环依赖?
1、什么是循环依赖所谓循环依赖是指,在A注入了B,在B中注入了A。初始化A时需要先初始化B,初始化B又需要初始化A,从而出现的类似死锁的现象。
2021-02-20
下一篇 
从0到1 - 带你了解线程池 从0到1 - 带你了解线程池
1. 线程线程是调度CPU的最小单位,线程模型分为 ULT 和 KLT。 JVM 使用的是KLT模型,java线程和操作系统os线程保持着一对一的映射关系,也就是说每创建一个java线程就意味着在操作系统里新建了一个os线程。
2020-12-22
  目录