MENU

Spring源码解析(二)Refresh()方法(一)

December 22, 2020 • Read: 2351 • 后端

前言:spring系列第二篇文章,前面懒病犯了。(笑)

本篇主要讲解context.refresh()方法

0. 准备工作

Test.Java

public class Test {
    public static void main(String[] args) throws IOException {
        // 把spring所有的前提环境准备好(比如:bean容器、bean工厂等)
        AnnotationConfigApplicationContext context = new
                AnnotationConfigApplicationContext();
        // 像容器注入配置类,后面来讲。
        context.register(AppConfig.class);
        // 本篇主要讲解的内容
        context.refresh();
        AppConfig bean = context.getBean(AppConfig.class);
        System.out.println(bean);            
    }
}

1. 源码阅读

Refresh()方法

方法处于AbstractApplicationContext类,方法里面做了很多的事情,首先我们点开这个方法:

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            // 准备工作包括:设置启动时间、是否激活标识位、初始化属性源(property source)配置
            // 和主流程关系不太大
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            // 得到beanFactory,然后对beanFactory进行设置
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            // 重点方法,准备beanFactory
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 空方法,当前版本没有代码
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                /*
                 * 在spring的环境中执行已经被注册的 factory processors
                 * 设置执行自定义和spring内部的beanFactoryPostProcessor
                 * 这里执行了了spring内部最关键的一个BeanFactoryPostProcessor:ConfigurationClassPostProcessor
                 */
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                // 注册bean的处理器来拦截bean的创建
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                // 这个方法不太重要。国际化
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                // 空壳方法
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                // 实例化所有剩余的不是懒加载的单例bean,又一个重点方法。
                // 何谓剩余?单例bean有两种:spring内置的、自己添加的(这就是代表剩余的)
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                // 最后一步:发布相应的事件
                finishRefresh();
                 // ... 省略后面的
        }
    }

里面有很多调用的方法,我们先一个一个的分析:

1.1 prepareRefresh()

正如其命名一样,该方法做的工作主要是:设置启动时间、是否激活标识位、初始化属性源(property source)配置等,与主流程关系不大。有兴趣的可以自己专研下。


1.2 obtainFreshBeanFactory()

取出得到beanFactory,然后对beanFactory进行设置。关于什么是beanFactory,简单来说就是一个工厂,里面有储存着所有要用的东西,等后面再来详细说明。


1.3 prepareBeanFactory()

// Prepare the bean factory for use in this context.
// 重点方法,准备beanFactory
prepareBeanFactory(beanFactory);

这是一个比较重要的方法,里面完成了很多工作:

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        // 设置一个类加载器
        beanFactory.setBeanClassLoader(getClassLoader());
        // bean的表达式解析,能够获取bean当中的属性,在前台页面
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        // 对象与字符串之间的转换
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks. 配置工厂的回调
        // 增加一个后置管理器。    ApplicationContextAwareProcessor 实现了BeanPostProcessor
        // ApplicationContextAwareProcessor 这个类也会在后面介绍的
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //最核心的

        // 以下接口,忽略自动装配
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        // ...省略部分

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        // 依赖的替换
        //以下接口,允许自动装配,第一个参数是自动装配的类型,,第二个字段是自动装配的值
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        // ...省略部分

        // Register early post-processor for detecting inner beans as ApplicationListeners.
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
        /*
         * 意思是如果自定义的Bean中没有名为"systemProperties"和"systemEnvironment"的Bean.
         * 则注册两个Bean,Key为"systemProperties"和"systemEnvironment",Value为Map,
         * 这两个Bean就是一些系统配置和系统环境信息
         */
        // Register default environment beans. 注册默认的环境bean
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        // ...省略部分
    }

主要做了如下工作:

  1. 设置一个类加载器
  2. bean的表达式解析,能够获取bean当中的属性,在前台页面
  3. 设置对象与字符串之间的转换的类
  4. 添加了一个后置处理器:ApplicationContextAwareProcessor,其实现了接口BeanPostProcessor(其作为spring扩展点之一,这个接口会在后面详细讲解的)
  5. 设置忽略自动装配的接口
  6. 相关依赖的替换
  7. 设置一些系统配置和系统环境信息

1.4 postProcessBeanFactory()

// 空方法,当前版本没有代码
postProcessBeanFactory(beanFactory);

这个方法是在标准初始化完成后,用于修改内部beanFactory的方法,当前版本没有实现,可能在后续的版本中增加相关的实现。


1.5 invokeBeanFactoryPostProcessors()

// Invoke factory processors registered as beans in the context.
/*
* 在spring的环境中执行已经被注册的 factory processors
* 设置执行自定义和spring内部的beanFactoryPostProcessor
* 这里执行了了spring内部最关键的一个BeanFactoryPostProcessor:ConfigurationClassPostProcessor
*/
invokeBeanFactoryPostProcessors(beanFactory);

这个方法是非常重要的一个方法,完成了非常重要的工作,这篇就讲个开始, 下一篇将重点讲解此方法里面内容。


protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // getBeanFactoryPostProcessors()方法是获取手动(这个是没有交给spring容器管理的,也就是没加@Component)
    /**
    * getBeanFactoryPostProcessors()返回的是AnnotationConfigApplicationContext继承的父类中被定义的
    * 一个List,是一个空的。
    * 是需要自己调用AnnotationConfigApplicationContext的addBeanFactoryPostProcessors()方法添加进去
    */
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    
 // ...省略部分内容
    }
}

1.5.1 getBeanFactoryPostProcessors()

先看这个方法:

getBeanFactoryPostProcessors()返回的是AnnotationConfigApplicationContext继承的父类中被定义的一个List,是一个空的。

是需要自己调用AnnotationConfigApplicationContext的addBeanFactoryPostProcessors()方法添加进去。

addBeanFactoryPostProcessor()方法

public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
    // ....
    this.beanFactoryPostProcessors.add(postProcessor);
}

当没有手动调用add方法时,从截图可以清楚看到里面并没有内容

image-20201222211401516.png

当我们在Test类中的main方法中调用addBeanFactoryPostProcessor()方法时:

image-20201222211819682.png

可以从下图看出结果:

image-20201222212534962.png


本篇文章到这就完结,后面的内容,下篇文章再写。希望我能更新更快一点(逃

2. 参考链接

剑指Spring源码(二)