SpringBoot IoC(4)实例化与依赖注入

578 阅读5分钟

实例化

AbstractApplicationContext->refresh():
    finishBeanFactoryInitialization(beanFactory);
AbstractApplicationContext->finishBeanFactoryInitialization():
    beanFactory.preInstantiateSingletons();    
DefaultListableBeanFactory->preInstantiateSingletons():
    // 对beanDefinitionNames遍历
    for (String beanName : beanNames) {
        // 该RootBeanDefinition从mergedBeanDefinitions取出
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 只对单例和没有@Lazy注解的bean实例化
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 是否实现了FactoryBean接口
            if (isFactoryBean(beanName)) {
                ......
            } else {
                getBean(beanName);
            }
        }
AbstractBeanFactory->getBean():
    return doGetBean(name, null, null, false);
AbstractBeanFactory->doGetBean():
    // 如果name前缀有&的话会去掉
    final String beanName = transformedBeanName(name);
    // 从singletonObjects取出,如果有值,说明已经实例化完成
    Object sharedInstance = getSingleton(beanName);
    ......
    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    // 如果bean声明了依赖,会先实例化它的依赖
    String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
        ......
    }
    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
            try {
                return createBean(beanName, mbd, args);
            }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    } else if (mbd.isPrototype()) {
        // 如果作用域是原型的话,每次调用都会生成
        ......
    } else {
        // 处理其他作用域
        .....
    }

从上面代码可以得到以下结论:

  1. 无论什么类型的BeanDefinition,实例化的时候都会转为RootBeanDefinition
  2. 启动阶段,IoC容器只会对没有@Lazy注解的单例bean实例化
  3. 对于bean不同的作用域有不同的处理方式,成员变量singletonObjects保证了单例bean在容器中只会有一个实例化对象

后续调用最终进入AbstractAutowireCapableBeanFactory->doCreateBean()方法,在这之前还有一些不可遗漏的小细节:

  1. 注意到DefaultSingletonBeanRegistry->getSingleton()方法有beforeSingletonCreation(beanName)afterSingletonCreation(beanName),这两句与循环依赖有关系。
  2. AbstractAutowireCapableBeanFactory->createBean()Object bean = resolveBeforeInstantiation(beanName, mbdToUse),它的作用是给后置处理一个返回代理的机会,一般返回都为空,这里会执行后置处理器的postProcessBeforeInstantiation()方法,如果有AnnotationAwareAspectJAutoProxyCreator这个后置处理器,此时将会提前解析AoP方法

@Autowired依赖注入

/**
* 这一段代码的作用就是提前找到依赖注入的字段、初始化方法、销毁方法
* 1.放到不同后置处理器的缓存map中
* 2.设置bd的externallyManaged...属性值
* 3.最后将bd的postProcessed置为true
*/
AbstractAutowireCapableBeanFactory->doCreateBean():
    // 选取最合适的构造方法实例化对象
    instanceWrapper = createBeanInstance(beanName, mbd, args);
    if (!mbd.postProcessed) {
        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        mbd.postProcessed = true;
    }
AbstractAutowireCapableBeanFactory->applyMergedBeanDefinitionPostProcessors():
    // 遍历IoC容器的beanPostProcessors,当为autowiredAnnotationBeanPostProcessor时
    bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
AutowiredAnnotationBeanPostProcessor->postProcessMergedBeanDefinition():
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
AutowiredAnnotationBeanPostProcessor->findAutowiringMetadata():
    // 第一次进入,metadata肯定为null,所以肯定会走到这一步
    // 方法的主要作用就是反射遍历field字段,找出所有带@Autowired或@Value的字段,然后返回
    metadata = buildAutowiringMetadata(clazz);
    // injectionMetadataCache存入,便于下一次从缓存中获取
    this.injectionMetadataCache.put(cacheKey, metadata);
/**
*这一段代码的作用就是依赖注入
*/
AbstractAutowireCapableBeanFactory->doCreateBean():
    populateBean(beanName, mbd, instanceWrapper);
AbstractAutowireCapableBeanFactory->populateBean():
    // 如果自动注入模式是AUTOWIRE_BY_NAME或者AUTOWIRE_BY_TYPE的话,实例化要自动注入的对象
    if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
        // --3
        ......
    }
    // 遍历IoC容器的beanPostProcessors,这里分析当为autowiredAnnotationBeanPostProcessor时
    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    ......
    // 经过自动注入模式过程后,有要自动注入的对象,则调用set方法注入
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
AutowiredAnnotationBeanPostProcessor->postProcessProperties():
    // 前面已存入,此处直接取就是了
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
    	metadata.inject(bean, beanName, pvs);
    }
InjectionMetadata->inject():
    // elementsToIterate是所有@Autowired的字段
    for (InjectedElement element : elementsToIterate) {
        // element封装了需要注入的字段
        element.inject(target, beanName, pvs);
    }
AutowiredAnnotationBeanPostProcessor->AutowiredFieldElement->inject():
    // --1 
    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    ......
    // 利用反射完成注入
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
DefaultListableBeanFactory->resolveDependency(): // --1
    // --2 是否懒加载
    Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
    if (result == null) { 
        result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); 
    }
    return result;
DefaultListableBeanFactory->doResolveDependency()
    // IoC候选和初筛候选
    matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    ......
    // 当beanName不止一个的时候,最终候选
    if (matchingBeans.size() > 1) {
        autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    }
    ......
    // 然后实例化beanName 
    // instanceCandidate是一个反射类,执行完if语句后成为一个对象实例
    if (instanceCandidate instanceof Class) {
        // 调用的beanFactory.getBean(beanName)方法
        instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    }

--3处,得到autowireMode自动注入模式属性值,如果是AUTOWIRE_BY_NAME的话,调用getBean(String name)实例化,如果是AUTOWIRE_BY_TYPE的话,流程与--1一样。关于它要自动注入的对象参见AbstractBeanDefinition属性说明中的autowireMode 自动注入模式

--2处,如果字段使用懒加载注解的话,直接返回代理了,这种情况暂时不考虑,关于懒加载的后续说明请点击此处

总结:

  1. 对bean分析,提前获取需要注入的字段
  2. 依赖注入方法中,依次遍历,根据字段的类型、名称或是bean信息反推beanName,然后实例化
  3. 利用反射field.set()方法,完成注入

根据@Autowired注解获取bean举例:

  • IoC候选由field.getType()推断而来,调用的是getBeanNamesForType(@Nullable Class<?> type)方法
情况IoC候选初筛候选最终结果说明
@Autowired private Demo demo1demo\demoIoC候选就一个
@Autowired private Demo demodemo1,demo2demo1,demo2报错找到多个
@Autowired private Demo demo@Primary demo1,demo2demo1,demo2demo1由@Primary注解决定
@Autowired private Demo demo1demo1,demo2demo1,demo2demo1最终由field.getName() 决定
@Autowired @Qualifer("demo1") private Demo demo1demo1,demo2demo1demo1初筛由@Qualifer("demo1") 决定
@Autowired @Qualifer("demos") private Demo demo1demo1报错找不到demos的候选名称

举一反三:

1.对于@Resource,@Value的注入,都是在populateBean()方法中完成的,只不过是不同的Bean后置处理器起的作用而已
2.如果是通过构造器注入的,会找到对应构造器,然后使用反射方法constructor.newInstance()完成实例化。构造器的参数同样经历总结中1、2的步骤

附录:beanFactory常用方法

  • getBean(String name) 根据beanName获取bean,与实例化过程相同
  • getBeanNamesForType(@Nullable Class<?> type) 根据beanClass返回beanName数组。如果有缓存则直接取缓存,否则遍历beanDefinitionNames和manualSingletonNames,找到beanName对应的beanClass,如果是目录类或者目标类的子类则添加
  • getBean(String name, Class<T> requiredType) 先根据beanName获取bean,然后判断该bean是否为requiredType类或子类,如果是的话返回,否则抛出异常
  • getBean(Class<T> requiredType) 根据beanClass获取bean。先调用getBeanNamesForType(@Nullable Class<?> type)获取beanClass对应的beanName,然后调用getBean(String name, Class<T> requiredType)返回bean
  • getBeansOfType(@Nullable Class<T> type) 根据beanClass获取beanName和bean。先调用getBeanNamesForType(@Nullable Class<?> type)获取beanClass对应的beanName,然后调用getBean(String name)得到bean,将beanName与bean放入map中,最后返回map
  • getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) 根据annotationClass获取beanName数组。每次都遍历beanDefinitionNames和manualSingletonNames,如果beanClass声明注解及子注解有符合annotationClass的注解则添加
  • getBeansWithAnnotation(Class<? extends Annotation> annotationType) 根据annotationClass获取bean数组。先调用getBeanNamesForAnnotation(Class<? extends Annotation> annotationType)获取注解对应的beanName,然后调用getBean(String name)获取bean

  • registerSingleton(String beanName, Object singletonObject) 手动注入IoC容器单例bean,如果beanName已在容器中,会报错。若beanDefinitionMap不存在则添加到manualSingletonNames
  • getBeanPostProcessors() 获取后置处理器集合,返回的是成员变量beanPostProcessors
  • addBeanPostProcessor(BeanPostProcessor beanPostProcessor) 手动添加后置处理器
  • registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 手动注入到bdm和bdn