美文网首页
Spring IOC的创建原理

Spring IOC的创建原理

作者: Coding小聪 | 来源:发表于2018-06-11 23:10 被阅读14次

前言

我们将通过Spring(具体版本为:4.3.9.RELEASE)注解的方式来分析IOC容器的创建过程,主要通过AnnotationConfigApplicationContext类。入口程序如下

@Test
public void test(){
    AnnotationConfigApplicationContext applicationContext = new
          AnnotationConfigApplicationContext(MainConfig.class);
    System.out.println("IOC容器创建完毕");
    Object person = applicationContext.getBean("person");
    Person person1 = applicationContext.getBean(Person.class);
    System.out.println(person == person1);
}

其中MainConfig是Spring的注解配置类,其代码如下

@Configuration
public class MainConfig {

    /**
     * @Bean注解的value属性用来定义注册到IOC容器中的bean name
     * 如果不指定value属性,则用方法名作为bean name
     * @return
     */
    @Bean(value = "person")
    public Person getPerson(){
        Person person = new Person();
        person.setName("Jerry");
        person.setAge(18);
        person.setNickName("J");
        return person;
    }
}

AnnotationConfigApplicationContext的继承体系

AnnotationConfigApplicationContext继承体系图
由上图可知,AnnotationConfigApplicationContextApplicationContext接口某个具体实现类,而ApplicationContextBeanFactory的子接口。所以我们可以将AnnotationConfigApplicationContext看成是一种BeanFactory,他们的本质都是一样的。

ApplicationContext和BeanFactory都是用于加载Bean的,这两个类都可以看成是Spring IOC容器,但是ApplicationContext比BeanFactory提供了更多的扩展功能。

常见的ApplicationContext


上图中用红框框起来的是一些常见的ApplicationContext,它们用于各种不同的场景。在这些类实例化的过程中,都会直接或间接的调用AbstractApplicationContext.refresh()方法。而AbstractApplicationContext.refresh()方法的执行过程就是IOC容器的创建过程。下面来分析一下refresh()方法的执行过程。

refresh()执行流程

refresh()方法很重要,它是各种IOC容器初始化的入口。首先需要知道的是refresh()方法运用了“模板方法”的设计模式,后面会出个专栏分析Spring中运用的设计模式。先来看看refresh()的源码

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 准备上下文信息
        prepareRefresh();
        // Tell the subclass to refresh the internal bean factory.
        // 2. 初始化BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 3. 对BeanFactory进行功能填充
        prepareBeanFactory(beanFactory);

        try {
            // 4. 子类覆盖的方法,用于做特殊的处理,这是个钩子方法
            postProcessBeanFactory(beanFactory);
            // 5. 激活各种BeanFactoryPostProcessor处理器
            invokeBeanFactoryPostProcessors(beanFactory);
            // 6. 注册各种Bean的后置处理器,后置处理器的调用发生在getBean
            registerBeanPostProcessors(beanFactory);
            // 7. 国际化处理
            initMessageSource();
            // 8. 在容器中初始化消息广播器
            initApplicationEventMulticaster();
            // 9. 子类覆盖的方法,各⼦类来初始化其他的bean,钩子方法
            onRefresh();
            // 10. 注册Listener到消息广播器中
            registerListeners();
            // 11. 初始化剩余的所有非懒加载的单实例bean
            finishBeanFactoryInitialization(beanFactory);
            // 12. 发送ContextRefreshEvent广播,完成刷新过程
            finishRefresh();
        } catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        } finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            // 13. 清除缓存
            resetCommonCaches();
        }
    }
}

refresh()正常执行完毕,即表明创建好IOC容器。分析源码可以知道refresh()方法做了13件事。

  1. 准备上下文信息;
  2. 创建BeanFactory;
  3. 对BeanFactory进行功能填充;
  4. 子类覆盖的方法,用于做特殊的处理,这是个钩子方法;
  5. 激活各种BeanFactoryPostProcessor处理器;
  6. 注册各种Bean的后置处理器,后置处理器的调用发生在getBean;
  7. 国际化处理;
  8. 在容器中初始化消息广播器;
  9. 子类覆盖的方法,各⼦类来初始化其他的bean,钩子方法;
  10. 注册Listener到消息广播器中;
  11. 初始化剩余的所有非懒加载的单实例bean;
  12. 发送ContextRefreshEvent广播,完成刷新过程;
  13. 清除缓存。

1. 准备上下文信息

protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }

    // 初始化property资源,扩展点,留给子类实现
    initPropertySources();

    // 验证需要的配置文件是否加载到环境中
    // see ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();

    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

2. 创建BeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

这个方法执行完毕之后,ApplicationContext就拥有了BeanFactory的功能。这段代码做了两件事:2.1 初始化BeanFactory;2.2 获取BeanFactory。

2.1 初始化BeanFactory

refreshBeanFactory();用来初始化BeanFactory,它最终调用的是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());
}

主要是通过getId()方法给BeanFactory设置serializationId的属性值,此处设置的值为:"org.springframework.context.annotation.AnnotationConfigApplicationContext@6cc7b4de"

2.2 获取BeanFactory
public final ConfigurableListableBeanFactory getBeanFactory() {
    return this.beanFactory;
}

此处返回的是DefaultListableBeanFactory

3. 对BeanFactory进行功能填充

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    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.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));

    // 增加对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());
    }
}

此方法是对BeanFactory进行一些设置。关于这一块的解说可以参考容器的功能扩展(二)功能扩展

4. postProcessBeanFactory

postProcessBeanFactory方法是一个扩展点,在AbstractApplicationContext中是一个空方法,它主要是让子类可以重写以实现它们自己的特殊逻辑。而AnnotationConfigApplicationContext并没有对该类进行重写。

5.激活各种BeanFactoryPostProcessor处理器

BeanFactoryPostProcessorBeanPostProcessor都是Spring提供的扩展点,可以通过它们对bean的定义修改。

 protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
     PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

     // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
     // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
     if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
         beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
         beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
     }
 }

激活BeanFactoryPostProcessor的工作会委托给PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()进行处理。

6. 注册各种Bean的后置处理器

Bean的后置处理器的方法也是委托给PostProcessorRegistrationDelegate处理,具体方法为:registerBeanPostProcessors()。这⾥只是注册,真正的调⽤是在getBean的时候

待续

相关文章

  • Spring IOC源码最全分析

    IOC 控制反转 1. Spring IOC 的原理? spring ioc 即控制反转,就是将我们创建和管理对象...

  • Spring

    什么是 IOC ,了解 Spring IOC 的原理吗? IOC/DI:控制反转,本质是将原来程序中对象创建、依赖...

  • Spring orm原理

    Spring工作原理 1、spring原理 内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以...

  • Spring_IOC_04——Bean的作用域

    其他推荐:Spring_IOC_01——概念讲解Spring_IOC_02——原理解析Spring_IOC_03—...

  • Spring IOC的创建原理

    前言 我们将通过Spring(具体版本为:4.3.9.RELEASE)注解的方式来分析IOC容器的创建过程,主要通...

  • 2019-05-23 Spring IOC 学习

    一、Spring Ioc/AOP 底层原理 1 IoC 引用 Spring 官方原文:This chapter c...

  • Spring要点

    1.spring IOC AOP原理: IoC(Inversion of Control): IoC就是应用本身...

  • IOC

    IOC(概念和原理) 什么是IOC? 反转控制,把对象创建和对象之间的调用过程,交给Spring进行管理 使用IO...

  • 2.IOC原理分析

    要想使用Spring IOC,必须要创建Spring IOC容器 ? 什么是IOC容器? 所谓的IoC容器就是指的...

  • 理解Spring IOC

    TODO:未来按自己的思路和理解再整理 IOC概念 阅读:Spring的IOC原理 Spring中IOC实现 阅读...

网友评论

      本文标题:Spring IOC的创建原理

      本文链接:https://www.haomeiwen.com/subject/dmukeftx.html