Spring IoC源码分析(注解版) -- 下

前两篇我们讲了BeanDefinition加载以及BeanFactory后置处理器,主要分析了registry和invokeBeanFactoryPostProcessors这两个方法。今天我们来分析另外两个重要的方法。registerBeanPostProcessors和finishBeanFactoryInitialization。这些方法都在AnnotationConfigApplicationContext的refresh方法中。

注册Bean 后置处理器

registerBeanPostProcessors方法负责初始化实现了BeanPostProcessor接口的Bean,并将其注册到BeanFactory中。

后置处理器BeanPostProcessor定义了两个方法postProcessBeforeInitialization和postProcessAfterInitialization。Spring会添加所有的BeanPostProcessor到BeanFactory的beanPostProcessors列表中。

BeanPostProcessor可以理解成辅助类,在所有其它类型的Bean(应用Bean)初始化过程中,Spring会分别在它们初始化前后调用BeanPostProcessor实例的postProcessBeforeInitialization和postProcessAfterInitialization。

前面讲的BeanFactoryPostProcessor,和BeanPostProcessor是一样的。在BeanFactory创建之后,Spring会调用所有BeanFactoryPostProcessor实例的postProcessBeanFactory方法,这样为用户提供了在BeanFactory创建之后,对Bean进行扩展的机会。

现在来看registerBeanPostProcessors源码:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 调用PostProcessorRegistrationDelegate的registerBeanPostProcessors方法
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }

看PostProcessorRegistrationDelegate的registerBeanPostProcessors的源代码:

public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
        // 获取所有的postProcessor names
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        
        List nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            // 放到nonOrderedPostProcessorNames列表中,这里省略了其它代码,都是处理优先级的。BesnPostProcessor也可以设置优先级的,优先级高的会先被调用。                      
            nonOrderedPostProcessorNames.add(ppName);
        }

        

        // Now, register all regular BeanPostProcessors.
        List nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            // 实例化BeanPostProcessor实例
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
        }
    
        // 注册BestProcessor
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    }

看registerBeanPostProcessors源码:

private static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List postProcessors) {

        // 把所有的BeanPostProcessor添加到beanFactory中
        for (BeanPostProcessor postProcessor : postProcessors) {
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }

beanFactory是一个DefaultListableBeanFactory对象,我们来看其代码,很简单,几乎就是一行代码:

@Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {     
        // Remove from old position, if any
        this.beanPostProcessors.remove(beanPostProcessor);      
        // 将beanPostProcessor添加到beanPostProcessors列表中
        this.beanPostProcessors.add(beanPostProcessor);
    }

在创建所有的应用bean调用initializeBean方法时,会轮询beanPostProcessors中的对象,并在Bean实例化前后分别调用postProcessBeforeInitialization和postProcessAfterInitialization方法。

好的,注册BeanPostProcessor讲完了,注册过程比较简单,主要是讲了一下它在Spring Bean初始化过程中的作用。我们接下来看最最重要的一个方法finishBeanFactoryInitialization。

初始化Bean对象

refresh方法中我们最后要讲的一个方法是finishBeanFactoryInitialization,它负责根据BeanDefinition创建Bean对象,并执行一些与Bean生命周期相关的回调函数。我们直接看源码:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 省略其它处理代码,直接调用beanFactory的preInstantiateSingletons.
        beanFactory.preInstantiateSingletons();
    }

始终记住beanFactory是DefaultListableBeanFactory对象,所以看它的preInstantiateSingletons源码。

// 这里要注意,只初始化所有singletons的Bean,关于prototype类型的bean,是每次调用getBean都会创建的,不会在容器启动的时候初始化。
public void preInstantiateSingletons() throws BeansException {      
        List beanNames = new ArrayList<>(this.beanDefinitionNames);     
        for (String beanName : beanNames) {
            // 这里省略了FactoryBean对象处理逻辑,如果是isEglarBean,也会调用getBean方法。所以简单理解为,不管是哪种sigleton bean,都会调用getBean方法
            getBean(beanName);
        }

        // 省略SmartInitializingSingleton的处理,有兴趣的可以去了解一下这个类的作用...     
    }

public Object getBean(String name) throws BeansException {
        // getBean其实调用了doGetBean方法。
        return doGetBean(name, null, null, false);
    }

来看doGetBean的代码,为了减少文章内容,只贴了核心代码:

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

        // 取单利Bean,这里简单介绍一下DefaultListableBeanFactory的另一种集成关系,它继承了DefaultSingletonBeanRegistry类。这个类允许单利管理,简单讲就是其中定义了一个HashMap,维护了bean名字和Bean对象的关系,并且保证每一个Bean名字只创建一个Bean对象。
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            // 如果缓存(上面说的HashMap)中存在bean,则取这个bean
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // BeanFactory是可以继承的,如果当前BeanFactory中找不到Bean定义,就从父BeanFactory中去找。
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                // 省略了参数处理的过程。直接从父BeanFactory去找。
                return (T) parentBeanFactory.getBean(nameToLookup);
            }           

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 这里先处理Bean依赖,如果当前Bean依赖其它Bean,则先注册并实例化依赖的Bean.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        // 先注册依赖Bean
                        registerDependentBean(dep, beanName);
                        // 再实例化依赖Bean
                        getBean(dep);
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        // 创建单利Bean
                        return createBean(beanName, mbd, args);
                        
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // Prototyp类型的Bean,是每次都会创建的。
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    // 处理其它类型的Bean,如一些扩展的类型Session,Request等等,代码省略了..
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // 类型转换的代码也省略了...
        return (T) bean;


来看一下createBean做了哪些事情。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){  
        // 其它代码都省略了,就是调用了doCreateBean方法
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }

来看doCreateBean的代码:

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

        // 创建BeanWrapper.
        BeanWrapper instanceWrapper = null;     
        if (instanceWrapper == null) {
            // 调用createBeanInstance创建Bean实例,这个方法我们不再仔细往下阅读了,大致的思路是根据RootBeanDefinition找到其类型classType,然后再获取其构造函数,然后根据构造函数使用反射动态创建出一个bean实例,再对这个实例进行一下包装,返回BeanWrapper对象。当需要对bean增强的时候,创建bean也可能使用CGLib动态创建,我们这里只讲最简单的情况。
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();       

        
        Object exposedObject = bean;
        try {
            // 根据BeanDefinition对bean属性进行赋值。
            populateBean(beanName, mbd, instanceWrapper);
            // 初始化Bean,在这里执行Bean生命周期的回调函数,如设置beanName,调用postBestProcessor等。
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {          
        }

        return exposedObject;
    }

上面的两个重要方法分别是createBeanInstance和initializeBean。其中createBeanInstance所做的事情大致是根据RootBeanDefinition找到其类型classType,然后再获取其构造函数,然后根据构造函数使用反射动态创建出一个bean实例,再对这个实例进行一下包装,返回BeanWrapper对象。因为这个类的业务很简单,大部分代码都是在处理一些与反射有关的东西,所以我们不再进行分析了。我们把重点放在initializeBean这个方法上。

来看initializeBean的代码:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        // 执行*Aware接口的方法,Spring提供了大量的*Aware接口,用来给Bean设置值,如可以向Bean中注入ApplicationContext,ClassLoader等。    
        invokeAwareMethods(beanName, bean);

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 如果Bean实现了BeanPostProcessor接口,则执行postProcessBeforeInitialization方法。
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 执行bean初始化相关方法。如果bean实现了InitializingBean接口,则会调用其afterPropertiesSet方法。如果bean指定了用户自定义的init-method方法,自定义方法也会被执行。
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // 如果Bean实现了BeanPostProcessor接口,则执行postProcessAfterInitialization方法。
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

上面代码中相关接口方法的执行都很直接,就是判断Bean对象是否实现了某个接口,如果实现了该接口,就调用接口定义的方法。initializeBean是比较重要的方法,它涉及到了Bean的生命周期,是面试的常考点。它也确实比较重要,我们可以在Bean初始化期间做很多事情。

到目前为止,Bean初始化也讲完了,从finishBeanFactoryInitialization->getBean->createBean->initializeBean。完成了bean的初始化并执行Bean生命周期中相关的回调方法。

总结

今天讲了注册bean后置处理器以及bean的加载。

Spring定义了BeanPostProcessor接口,所有实现了该接口的bean,都将被注册到spring的后置处理器列表中。后置处理器相当于是一些辅助类,所有的应用bean在初始化之后,都会调用所有的后置处理器。这为用户提供了在bean初始化前后,修改或扩展bean的机会。

然后我们讲了最重要的bean加载。ApplicationContext会在启动容器时,加载所有的非lazi-init的singleton bean。ApplicationContext实现了BeanDefinitionRegistry接口,并在之前就已经注册了所有的BeanDefination,将其存储在一个HashMap中。在加载bean时,从HashMap中读取所有的BeanDefinition,并调用其getBean方法。getBean本意是获取bean,但是如果没有,则会创建并进行初始化。

获取bean时调用了doGetBean方法,首先会检查当前bean是否有定义,如果没有定义,则会去父BeanFactory中去查找。并且它也会检查当前bean是否依赖其它bean,如果依赖其它bean,则会先创建所依赖的bean。

创建bean是根据BeanDefinition中的classType,获取其构造函数,然后利用反射创建bean实例,然后调用populateBean方法进行属性设置,最后调用initializeBean回调一些与bean生命周期有关的接口方法。

至此,整个Spring的容器就启动了。


所有文章在Github上同步,你也可以访问我的个人博客点击查看

你可能感兴趣的