专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Spring IoC源码之 refresh()_01

Spring容器初始化 refresh() 方法_01

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    /**
     * 调用默认的构造方法,由于该类有父类,
     * 故而先调用父类的构造方法,在调用自己的构造方法
     * 在自己的构造方法中初始一个读取器和一个扫描器,
     * 第①部分!!!
     */
    this();
    /**
     * 向spring 的容器中注册bean
     * 第②部分!!!
     */
    register(componentClasses);
    /**
     * 初始化spring的环境
     * 第③部分!!!
     */
    refresh();
}

  这里将要解析上述代码中的refresh()这一部分的代码。。。

refresh()方法实现

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        /*
         * 准备工作包括设置启动时间,是否激活标识位
 * 初始化属性源(property source)配置 */ prepareRefresh(); /* * 获取 DefaultListableBeanFactory 对象,后续会对BeanFactory设置 * 在子类中启动refreshBeanFactory()的地方 */ ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); /* * 准备BeanFactory */ prepareBeanFactory(beanFactory); try { /** 当前未写任何代码,是一个空方法*/ postProcessBeanFactory(beanFactory); /** * 在spring的环境中 执行已经被注册的 BeanFactoryPostProcessors * 设置执行自定义的 ProcessorBeanFactory * 这里是重点代码 */ invokeBeanFactoryPostProcessors(beanFactory); /** 注册spring Bean 的后置处理器*/ registerBeanPostProcessors(beanFactory); /** 对上下文中的消息源进行初始化*/ initMessageSource(); /** 初始化上下文中的事件机制*/ initApplicationEventMulticaster(); /** 没有具体实现的方法*/ onRefresh(); /** 检查监听bean并且将这些Bean向容器注册*/ registerListeners(); /** Bean的实例化*/ finishBeanFactoryInitialization(beanFactory); /** 发布容器事件,结束refresh过程*/ finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } /** 为防止Bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件bean*/ destroyBeans(); /** 重置 active 标志*/ cancelRefresh(ex); throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } } 

refresh()时序图

121_1.png refresh时序图

  上述的流程图中,在AbstractApplicationContext#refresh()发放中有10多个流程,一起看一下每个流程的细节。 这个refresh()方法是IoC容器的核心方法,无论是基于Xml形式的,还是基于注解形式的方法都会调用这个方法,来完成容器的初始化。

1.prepareRefresh()方法

  该方法包括主要是完成:准备工作包括设置启动时间,是否激活标识位;初始化属性源(property source)配置。

protected void prepareRefresh() {
    // Switch to active.
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
 if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } /** * 留给子类覆盖 * 符合spring的开放式结构设计,给用户扩展spring提供了可能 * 用户可根据自身需要重写initPropertySources()方法,并在方法中进行个性化 * 的属性处理及设置 * 第①处!!! */ initPropertySources(); /** 验证需要的属性文件是否都已经放入环境中*/ getEnvironment().validateRequiredProperties(); /** 存储预先刷新的容器监听器*/ if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // Reset local application listeners to pre-refresh state. this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); } 

  其中第一处的代码,是一个空壳方法,spring并没有实现。留做以后子类扩展使用,具体代码如下

protected void initPropertySources() {
    // For subclasses: do nothing by default.
}

2.obtainFreshBeanFactory()方法

  该方法是获取BeanFactory的地方,这里一般都是获取Spring 默认的实现DefaultListableBeanFactory. 这获取BeanFactory的实现时,这里采用委派设计模式,将其交给不同的子类去实现。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    /** 这里使用了委派设计模式,父类定义了抽象方法,具体的实现通过子类实现 */
    refreshBeanFactory();
    /** 返回当前实体的 beanFactory属性 */
    return getBeanFactory();
}

  在这里,我采取的是基于注解的方式,最终执行的代码是GenericApplicationContext#refreshBeanFactory()方法。

protected final void refreshBeanFactory() throws IllegalStateException {
    if (!this.refreshed.compareAndSet(false, true)) {
        throw new IllegalStateException(
                "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
    }
    this.beanFactory.setSerializationId(getId());
}

  同理这里的getBeanFactory()方法,也会到GenericApplicationContext中执行getBeanFactory()方法, 最终获取到的是在之前初始化好的DefaultListableBeanFactory对象。

public final ConfigurableListableBeanFactory getBeanFactory() {
    return this.beanFactory;
}

3.prepareBeanFactory(beanFactory)方法

  该方法是准备BeanFactory的方法,配置BeanFactory的标准特征,比如上下文的加载器 ClassLoader 和 post-processors 回调等。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    /** 设置bean的类加载器*/
    beanFactory.setBeanClassLoader(getClassLoader());
    /** 设置bean表达式解释器*/
 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); /** * 工厂中添加一个bean的后置处理器 * 目的就是 注册一个 BeanPostProcessor,真正的逻辑是在 ApplicationContextAwareProcessor * 在bean实例化的时候,spring 激活 bean的 init-method 前后 会调用 BeanPostProcessor 的 * postProcessAfterInitialization() 和 postProcessBeforeInitialization() * 因此,这里 要看一下 ApplicationContextAwareProcessor 类中的这两个方法 */ beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); /** * 自动注入被忽略的类 * spring 将 ApplicationContextAwareProcessor 注册后,在invokeAwareInterfaces() * 方法中间接调用的 Aware 类已经不再是 普通的 Bean 了,如: * ResourceLoaderAware, ApplicationEventPublisherAware, ApplicationContextAware 等 * 那么就要在spring 做依赖注入的时候忽略掉它们,ignoreDependencyInterface() 就是这个作用。 */ beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. /** * 设置几个自动装配的特殊规则 * 注册依赖注入的功能,如,当对注册了对 BeanFactory 的依赖解析后, * 当 bean 的属性注入的时候,一旦检测到 属性为 BeanFactory 类型 * 便将 beanFactory 的实例注入进去 */ beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. /** 增加对AspectJ的支持*/ 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*/ if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } } 

  可以在上述文章中看出,Spring 中内置的 Bean 的后置处理器 ApplicationContextAwareProcessor 也被加入到了容器中。关于内置处理器,在 Spring中定义了一个 List 来存放。该 List 的定义如下:

private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

  在上述方法中对Spring 监听器相关的 BeanPostProcessor 实现 ApplicationListenerDetector,也被添加到了容器中。

4.postProcessBeanFactory()

   postProcessBeanFactory() 同样也是一个空方法,交给子类实现。

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

容器形成图

121_2.png   在上述的Spring IoC 的 refresh() 方法的调用过程中 prepareBeanFactory() 方法,将内置的 BeanPostProcessor添加到容器中。

本文使用 mdnice 排版

文章永久链接:https://tech.souyunku.com/28081

未经允许不得转载:搜云库技术团队 » Spring IoC源码之 refresh()_01

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们