SpringBoot源码解析(二)--自动注入过程(Autowired)

springboot 版本: 2.x
spring 版本 5.x

本篇文章主要分析下 Bean 属性的自动注入过程,并且会概要的分析下 Bean的实例化过程。

在上一篇文章中(https://www.jianshu.com/p/5d75c9bdf0c6)介绍了 springboot启动过程,其中也介绍了 bean的创建时机。其创建代码为 AbstractApplicationContext类refresh()方法中的如下代码:

image.png

Java bean 的初始化以及 field 的注入,都是通过这个方法完成的。

在这之前我们首先要熟悉几个类:
DefaultListableBeanFactory :默认的 bean工厂,看下这个类的继承结构:

image.png

AbstractAutowireCapableBeanFactory:负责创建 bean。
DefaultSingletonBeanRegistry:负责存储已经创建出来的 bean。
AutowiredAnnotationBeanPostProcessor: BeanPostProcessor的派生类, 会被 AbstractAutowireCapableBeanFactory调用并负责注入 bean 的属性。(BeanPostProcessor 的注册时机可以参考上一篇文章https://www.jianshu.com/p/5d75c9bdf0c6)

OK,一些必要的概念已经介绍完了,总结下DefaultListableBeanFactory本质上是一个容器,它会负责创建bean,存储 bean, 还会负责给 bean 注入属性。

接下来 , It's show time.

AbstractApplicationContext finishBeanFactoryInitialization() 方法:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
               // 忽略代码。。。

        // Instantiate all remaining (non-lazy-init) singletons.
        //负责创建非懒加载的单例的bean
        beanFactory.preInstantiateSingletons();
    }

DefaultListableBeanFactory preInstantiateSingletons() 方法:

public void preInstantiateSingletons() throws BeansException {
    //  忽略代码。。。

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 获取所有需要通过工程实例化的 bean 定义。
        List beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//非抽象类, 并且是单例的, 并且是非懒加载的,才会创建
                if (isFactoryBean(beanName)) {
                    //如果是 FactoryBean
                                        //忽略代码。。。
                        
                }
                else {
                          //非 FactoryBean, 也就是我们的 controller、service、dao 等等。。 
                         //创建 bean
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable 
// 忽略代码
    }

进入 getBean 方法,一路跟踪下去

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

进入 AbstractBeanFactory doGetBean()方法

protected  T doGetBean(final String name, @Nullable final Class requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        // 去缓存中获取 bean, 判断 bean 是否已经被创建
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            //忽略代码。。。。。
            
            //如果已经创建了,则直接将sharedInstance转为 bean, 一般情况下(service, controller...)这里的 bean 和sharedInstance指向的是同一个对象
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }  else {
            //如果此 bean 没有被创建,则执行下面常见 bean 的逻辑
            
            // 忽略代码。。。
            
            try {
            
                // 忽略代码。。。 话说 spring 的设计很精妙,但是代码实现确实不算优雅,一个方法太长了。。。。
                // Create bean instance.
                if (mbd.isSingleton()) {
                // 创建 bean, 这里用了 lamda表达式的匿名内部类的实现方式
                // 这个匿名内部类是ObjectFactory, 只有一个方法,getObject(), 其实先就是下面的代码
                // getSingleton()方法里面会调用 objectFactory.getObject()方法,实际执行的也就是createBean()方法。
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                // 忽略代码。。。。
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
   //忽略代码。。。
   
   
        return (T) bean;
    }

进入 createBean方法,即AbstractAutowireCapableBeanFactory类的 createBean() 方法

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        // 忽略一切。。。。
        try {
            //重点部分, 创建 bean
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }

进入 doCreateBean()方法,也在AbstractAutowireCapableBeanFactory中。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
        //创建bean, 也就是会调用 bean 的构造方法。 注意,这个方法虽然实例化了 bean,但是并没有给 bean 注入属性
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        
        //忽略代码。。。
        
        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    // 这里会缓存每个 bean的定义,也就是会初始化 bean 的元数据,其中包括 bean 有哪些需要注入的属性,
                    // 跟踪下去会发现其实调用的是AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition()方法
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }
    
      //忽略代码。。。
    
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            // 将实例化好的 bean,添加至缓存,也就是DefaultSingletonBeanRegistry singletonFactories属性中,
            // singletonFactories是一个 map, key 是 beanName, value 是这个 bean 对应的工厂。
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //此方法才是真正为 bean 注入属性的方法, 并且是递归注入,
            //依赖的是AutowiredAnnotationBeanPostProcessor ,这个类也是 BeanPostProcessor 的派生类。但是经过适配的,主要功能就是执行 autowired。
            //再注入属性实例的过程中,首先会去 DefaultSingletonBeanRegistry 缓存中判断实例是否初始化,如果已经初始化则直接赋值,否则执行上面一些列的 createBean, doCreateBean 方法实例化对象
            //因为实例化和注入是互相不依赖的, 所以即使出现循环依赖的情况: A 依赖 B, B 也依赖 A, 也不会出现问题。 
            //循环依赖的初始化过程如下,1. 初始化 A ; 2. 将 A 加入缓存;  3. 给 A 注入 B 对象; 4. 发现 B 没有初始化, 初始化 B.
            //5. 给 B 注入 A 对象,获取 A 时,发现A 再缓存中, 直接将 A 的实例赋值给B,支持 B 初始化且注入完成。 6. 将 B 的实例注入给 A。
            //至此 完成 A B 的初始化和注入。
            populateBean(beanName, mbd, instanceWrapper);
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        
        // 忽略 忽略。。。。

        return exposedObject;
    }

最后我们来看下是如何找到需要注入的 Autowired 属性的,也就是
AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition()方法

@Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }

进入findAutowiringMetadata()方法

private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) {
        // Fall back to class name as cache key, for backwards compatibility with custom callers.
        String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
        // Quick check on the concurrent map first, with minimal locking.
//首先判断缓存中是否存在
        InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized (this.injectionMetadataCache) {
                metadata = this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
//如果不存在则新建元数据
                    metadata = buildAutowiringMetadata(clazz);
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        return metadata;
    }

进入buildAutowiringMetadata()方法

private InjectionMetadata buildAutowiringMetadata(final Class clazz) {
        LinkedList elements = new LinkedList<>();
        Class targetClass = clazz;

        do {
            final LinkedList currElements = new LinkedList<>();

//又是一个匿名内部类,不过首先是doWithLocalFields()方法通过反射机制找到所有的 field
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
            //再找到被 Autowired注解注释的 field
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static fields: " + field);
                        }
                        return;
                    }
                    boolean required = determineRequiredStatus(ann);
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            });

            //忽略代码。。。。
        }
        while (targetClass != null && targetClass != Object.class);

        return new InjectionMetadata(clazz, elements);
    }

进入 ReflectionUtils.doWithLocalFields();

public static void doWithLocalFields(Class clazz, FieldCallback fc) {
        for (Field field : getDeclaredFields(clazz)) {
            try {
                fc.doWith(field);
            }
            catch (IllegalAccessException ex) {
                throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
            }
        }
    }


private static Field[] getDeclaredFields(Class clazz) {
        Assert.notNull(clazz, "Class must not be null");
        Field[] result = declaredFieldsCache.get(clazz);
        if (result == null) {
            try {
//最终还是反射
                result = clazz.getDeclaredFields();
                declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
            }
            catch (Throwable ex) {
                throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() +
                        "] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
            }
        }
        return result;
    }

首先通过反射找到所有的 field,再区分出被 autowired注释的 field(本部分比较复杂,本文不做分析了),然后再通过反射给这些 field 的赋值(这部分也比较简单,就是 Invoke 一下 set方法)。bean 的注入就完成了。

还是有很多细节的部分没有分析到,但是面面俱到也不现实,重要是要知道其思想和大致原理。

你可能感兴趣的:(SpringBoot源码解析(二)--自动注入过程(Autowired))