Spring源码分析之IOC

IOC(Inversion of Control),即控制反转,是面向对象编程中的一种设计原则,可以用来减低代码之间的耦合度。在Spring中,IOC意味着对象和资源的创建和获取统一交给了容器,由容器控制对象的生命周期和对象间的依赖关系。

而DI(Dependency Injection),即依赖注入,是实现IOC的一种手段。DI意味着组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。

要理解Spring IOC的实现,首先需要了解下面两个接口:BeanFactory和ApplicationContext

1. BeanFactory

BeanFactory是Spring中的Bean工厂, 用于Spring中Bean的生命周期管理。它的主要接口如下:

public interface BeanFactory {
    /*
     * 四个不同形式的getBean方法,获取实例
     */
    Object getBean(String name) throws BeansException;

     T getBean(String name, Class requiredType) throws BeansException;

     T getBean(Class requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    boolean containsBean(String name); // 是否存在

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;// 是否为单例

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 是否为原型(多实例)

    boolean isTypeMatch(String name, Class targetType)
            throws NoSuchBeanDefinitionException;// 名称、类型是否匹配

    Class getType(String name) throws NoSuchBeanDefinitionException; // 获取类型

    String[] getAliases(String name);// 根据实例的名字获取实例的别名
    
    //......
}

2. ApplicationContext

ApplicationContext是BeanFactory的子接口,在拥有所有BeanFactory功能的基础上,它还继承了一些其他接口:


Spring源码分析之IOC_第1张图片
ApplicationContext.jpg

因此,ApplicationContext拥有一些高阶功能,例如:

  • HierarchicalBeanFactory 是一个具有层级关系的 BeanFactory,拥有属性 parentBeanFactory。ListableBeanFactory 实现了枚举方法可以列举出当前 BeanFactory 中所有的 bean 对象而不必根据 name 一个一个的获取。
  • MessageSource接口提供国际化功能
  • ApplicationEventPublisher提供事件发布订阅功能
  • ResourceLoader提供资源加载功能
  • EnvironmentCapable用于获取 Environment 的功能

ApplicationContext常用实现类包括:ClassPathXMLApplicationContext, FileSystemXmlApplicationContext,AnnotationConfigApplicationContext和WebApplicationContext。

3. 容器入口

我们以ClassPathXmlApplicationContext为例,下面是其构造函数:

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }

Spring首先读取Config文件位置,然后调用refresh方法进行BeanFactory的构建。

4. 容器构建流程

下面是AbstractApplicationContext中refresh方法的实现:

public void refresh() throws BeansException, IllegalStateException {
  // refresh过程只能一个线程处理,不允许并发执行
  synchronized (this.startupShutdownMonitor) {
    prepareRefresh();
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    prepareBeanFactory(beanFactory);
    try {
      postProcessBeanFactory(beanFactory);
      invokeBeanFactoryPostProcessors(beanFactory);
      registerBeanPostProcessors(beanFactory);
      initMessageSource();
      initApplicationEventMulticaster();
      onRefresh();
      registerListeners();
      finishBeanFactoryInitialization(beanFactory);
      finishRefresh();
    }
    catch (BeansException ex) {
      if (logger.isWarnEnabled()) {
        logger.warn("Exception encountered during context initialization - " +
            "cancelling refresh attempt: " + ex);
      }
      destroyBeans();
      cancelRefresh(ex);
      throw ex;
    }
    finally {
      resetCommonCaches();
    }
  }
}

主要的流程图如下:


Spring源码分析之IOC_第2张图片
ApplicationContext refresh.png

4.1 prepareRefresh

执行一些初始化操作,包括记录当前时间,初始化变量等。其源码如下:

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

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

        // Initialize any placeholder property sources in the context environment
        initPropertySources();

        // Validate that all properties marked as required are resolvable
        // see ConfigurablePropertyResolver#setRequiredProperties
        getEnvironment().validateRequiredProperties();

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

4.2 obtainFreshBeanFactory

创建一个BeanFactory。此方法会调用refreshBeanFactory方法,其源码如下:

protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
}

从源码上看,refreshBeanFactory方法的主要流程如下:

  1. 若已经存在beanFactory,销毁它
  2. 创建新的beanFactory(new DefaultListableBeanFactory(getInternalParentBeanFactory()))
  3. 通过customizeBeanFactory定制BeanFactory的属性;
  4. 加载BeanDefinition到当前BeanFactory中(对于ClassPathXmlApplicationContext来说,会调用XmlBeanDefinitionReader读取所有的Bean定义,封装为BeanDefinition注册到BeanFactory中);

ApplicationContext实现了BeanFactory接口,其内部是通过聚合一个DefaultListableBeanFactory来实现所有的BeanFactory功能的。

下面时BeanDefinition接口的主要定义:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    //单例作用域
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

    //原型作用域
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    String getParentName();
    void setParentName(String parentName);

    String getBeanClassName();
    void setBeanClassName(String beanClassName);

    String getScope();
    void setScope(String scope);

    boolean isLazyInit();
    void setLazyInit(boolean lazyInit);

    boolean isPrimary();
    void setPrimary(boolean primary);

    boolean isSingleton();
    boolean isPrototype();
    //......
}

DefaultListableBeanFactory中维护了一个Map用于存储所有的BeanDefinition:

/** Map of bean definition objects, keyed by bean name */
private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);

另外,DefaultSingletonBeanRegistryDefaultListableBeanFactory的父类)中维护了一个Map用于存储所有的Bean:

/** Cache of singleton objects: bean name --> bean instance */
private final Map singletonObjects = new ConcurrentHashMap<>(256);

4.3 prepareBeanFactory

在BeanFactory已经创建成功后,Spring会调用prepareBeanFactory(beanFactory)来向已经创建的BeanFactory注册一些特定的Bean,包括environment等:

   // 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   // 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   // 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }

另外,还会注册一些BeanPostProcessor,包括ApplicationContextAwareProcessorApplicationListenerDetector等:

   // 添加一个 BeanPostProcessor,这个 processor 比较简单,
   // 实现了 Aware 接口的几个特殊的 beans 在初始化的时候,这个 processor 负责回调
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

   // 这个 BeanPostProcessor 也很简单,在 bean 实例化后,如果是 ApplicationListener 的子类,
   // 那么将其添加到 listener 列表中,可以理解成:注册事件监听器
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

4.3 postProcessBeanFactory

在BeanFactory基本完成后,Spring调用postProcessBeanFactory(beanFactory)来进行后续的针对BeanFactory的操作。AbstractApplicationContext中的默认实现为空。而其子类AnnotationConfigEmbeddedWebApplicationContext对应的postProcessBeanFactory方法则会扫描basePackage下的bean并注册到BeanFactory中。

4.4 invokeBeanFactoryPostProcessors

在BeanFactory创建完毕后,Spring调用invokeBeanFactoryPostProcessors(beanFactory)来运行所有已经注册的BeanFactoryPostProcessor,从而进行修改BeanFactory或修改BeanFactory中已经存在的BeanDefinition。

public interface BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

常见的BeanFactoryPostProcessor包括ConfigurationClassPostProcessorPropertyPlaceholderConfigurer等。

ConfigurationClassPostProcessor用于读取所有已经注册的Configuration类型的Bean,然后注入Configuration类中定义的Bean,最后判断该Configuration是否拥有ComponentScan注解,如果拥有则扫描basePackage下的所有bean并注册到BeanFactory中。

如果spring配置文件中包含了,spring则会自动启用ConfigurationClassPostProcessor

invokeBeanFactoryPostProcessors(beanFactory)方法内部首先对所有的BeanFactoryPostProcessor进行排序,然后依次调用。

4.5 registerBeanPostProcessors

registerBeanPostProcessors方法会对所有BeanFactory内的BeanPostProcessor类型的Bean进行排序,然后调用registerBeanPostProcessors注册这些BeanPostProcessor,最终在createBean时会依次调用这些BeanPostProcessor来customize最终生成的Bean。BeanPostProcessorBeanFactoryPostProcessor的区别在于,BeanPostProcessor用于实例化bean后再customize bean,而BeanFactoryPostProcessor则用于BeanFactory创建完成后customize BeanFactory。

BeanPostProcessor接口如下:

public interface BeanPostProcessor {
    // inti方法调用之前的操作
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    // init方法调用之后的操作
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

BeanPostProcessor调用时bean已经被实例化,并且所有该注入的属性都已经被注入,是一个完整的Bean。下面是postProcessBeforeInitializationpostProcessAfterInitialization的调用时间:

  1. 在Bean实例化完成后调用BeanPostProcessor.postProcessBeforeInitialization
  2. 如果Bean实现了InitializingBean接口,则调用InitializingBean.afterPropertiesSet方法
  3. 如果Bean中配置了init-method,则调用init-method
  4. 调用BeanPostProcessor.postProcessAfterInitialization

InitializingBean接口的定义如下:

public interface InitializingBean {

    /**
     * Invoked by a BeanFactory after it has set all bean properties supplied
     * (and satisfied BeanFactoryAware and ApplicationContextAware).
     * 

This method allows the bean instance to perform initialization only * possible when all bean properties have been set and to throw an * exception in the event of misconfiguration. * @throws Exception in the event of misconfiguration (such * as failure to set an essential property) or if initialization fails. */ void afterPropertiesSet() throws Exception; }

常见的BeanPostProcessor包括ApplicationContextAwareProcessorApplicationListenerDetectorAutowiredAnnotationBeanPostProcessor等。

ApplicationContextAwareProcessor用于调用Bean的Aware的接口(包括ApplicationContextAware,MessageSourceAware,ApplicationEventPublisherAware等)。例如如果Bean实现了ApplicationContextAware接口,在Bean实例化结束后,会调用ApplicationContextAware接口的setApplicationContext(ApplicationContext applicationContext)方法来cutomize实例化后的Bean。

ApplicationListenerDetector用于如果Bean实现了ApplicationListener接口,那么它会将这个Bean加入ApplicationEventMulticaster的listener列表中。

AutowiredAnnotationBeanPostProcessor用于注入所有使用了@Autowired注解的属性。

4.6 initMessageSource

MessageSource是Spring提供国际化的接口。ApplicationContext实现了MessageSource接口,其内部是通过聚合一个MessageSource对象来实现的。initMessageSource方法主要是为了初始化ApplicationContext内部的MessageSource对象。如果BeanFactory中存在一个MessageSource Bean,那么直接将这个Bean赋值给ApplicationContext内部的MessageSource对象。如果没有,则会构造一个new DelegatingMessageSource()对象。

4.7 initApplicationEventMulticaster

initApplicationEventMulticaster顾名思义,是为了初始化ApplicationEventMulticaster。ApplicationContext实现了ApplicationEventPublisher接口,从而具备了事件发布功能。其内部是通过聚合一个ApplicationEventMulticaster实现的。下面是初始化代码:

protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                        "': using default [" + this.applicationEventMulticaster + "]");
            }
        }
    }

initMessageSource方法类似,如果BeanFactory中存在一个名为applicationEventMulticaster的对象,则将其赋值给内部的this.applicationEventMulticaster。否则,直接通过new SimpleApplicationEventMulticaster(beanFactory)实例化一个ApplicationEventMulticaster。之后ApplicationContext所有事件发布功能都会转交给内部的applicationEventMulticaster对象。

ApplicationEventMulticaster主要负责事件的发布和监听者的注册。主要接口如下:

// 注册监听者
void addApplicationListener(ApplicationListener listener);
//发布事件
void multicastEvent(ApplicationEvent event);
//......

ApplicationEventMulticaster的实现类内部拥有一个Set> applicationListeners监听者集合。在扫描出所有实现了ApplicationListener接口的类后,通过以下方法创建一个ApplicationListener对象,然后添加到Set> applicationListeners监听者集合中。

public ApplicationListener createApplicationListener(String beanName, Class type, Method method) {
   return new ApplicationListenerMethodAdapter(beanName, type, method);
}

4.8 onRefresh

扩展方法,由子类实现用于初始化其他的特殊Bean。AbstractApplicationContext默认实现为空。

4.9 registerListeners

注册事件监听器。将BeanFactory中存在的ApplicationListener类型的Bean注册到ApplicationContext内部的ApplicationEventMulticaster中。

4.10 finishBeanFactoryInitialization

通过调用beanFactory.preInstantiateSingletons()实例化所有非懒加载的单例Bean。beanFactory.preInstantiateSingletons()则会遍历所有的Bean并调用getBean(beanName)方法。

下面是getBean(beanName)方法的流程:

  1. 首先通过getSingleton(beanName)从signleton缓存池中获取Bean
  2. 如果获取不到,则根据当前的beanfactory获取父一级的beanfactory,然后逐级递归的查找我们需要的bean
  3. 获取仍然不到则根据final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)拿到BeanDefinition,然后通过createBean(beanName, mbd, args)进行Bean的创建。
  4. createBean(beanName, mbd, args)方法调用doCreateBean(beanName, mbdToUse, args)方法来创建Bean。
  5. doCreateBean(beanName, mbdToUse, args)方法主要分为四步:
    (1) instanceWrapper = createBeanInstance(beanName, mbd, args) 通过反射创建出一个Bean实例
    (2)applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName) 调用所有的MergedBeanDefinitionPostProcessor来customize创建出的Bean。
    (3) populateBean(beanName, mbd, instanceWrapper) 填充所有的属性
    (4) exposedObject = initializeBean(beanName, exposedObject, mbd) 调用applyBeanPostProcessorsBeforeInitialization(即BeanPostProcessor.beforeInitialization),invokeInitMethods(即配置文件中配置的init-method)和applyBeanPostProcessorsAfterInitialization(即BeanPostProcessor.afterInitialization)

上文中我们提到的AutowiredAnnotationBeanPostProcessor是一种BeanPostProcessor(然而它的beforeInitialization和afterInitialization都为空),它还实现了MergedBeanDefinitionPostProcessor接口。因此上述第(2)步会调用AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition方法,然而这个方法并不会直接向Bean中注入所有的@Autowired属性。下面是这个方法的实现:

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

AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition的作用仅仅是缓存此Bean的所有@Autowired属性信息。

在执行第(3)步populateBean(beanName, mbd, instanceWrapper) 时,会调用其AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues方法,从而完成了所有@Autowired属性的注入:

@Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            metadata.inject(bean, beanName, pvs);
        }
        catch (BeanCreationException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }
        return pvs;
    }

更多Bean初始化流程,请参考:https://www.shangyang.me/2017/04/01/spring-core-container-sourcecode-analysis-beans-instantiating-process/

4.11 finishRefresh

执行refresh收尾工作。包括初始化LifecycleProcessor,发布ContextRefreshedEvent事件等。其源码如下:

protected void finishRefresh() {
        // Clear context-level resource caches (such as ASM metadata from scanning).
        clearResourceCaches();

        // Initialize lifecycle processor for this context.
        initLifecycleProcessor();

        // Propagate refresh to lifecycle processor first.
        getLifecycleProcessor().onRefresh();

        // Publish the final event.
        publishEvent(new ContextRefreshedEvent(this));

        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
}

参考文章:

  • https://www.shangyang.me/2017/04/01/spring-core-container-sourcecode-analysis-beans-instantiating-process/

你可能感兴趣的:(Spring源码分析之IOC)