2.IOC启动时序

IOC 启动时序

含义

IOC 即控制反转,可以理解为,将jvm中的对象,由程序员去控制声明周期,转为由容器去控制对象的声明周期。所以,在谈到 IOC时,都会说IOC容器。

bean 和 对象的区分

在spring的框架内,对象 + 受容器管理 = bean 。 所以,在Spring的框架内谈论的bean,准确地说,是受IOC容器管理地对象(这个对象可以是单例的,也可以是普通的)。

所以,学习 IOC的启动时序,就要搞清楚,IOC容器是怎么去管理bean,再结合启动的流程代码,就可以知道程序设计的目的。

BeanFactory :管理bean的工厂
BeanDefinition : 定义所有bean本身需要有的基本信息,比如元数据,字段属性,注入方式等
BeanPostProcessor : 对生成的 Bean 进行处理

IOC容器 BeanFactory

子类结构

image.png

先通过BeanFactory的源码看看,这个总接口定义了哪些功能

public interface BeanFactory {    
     
     //对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,    
     //如果需要得到工厂本身,需要转义           
     String FACTORY_BEAN_PREFIX = "&"; 
        
     //根据bean的名字,获取在IOC容器中得到bean实例    
     Object getBean(String name) throws BeansException;    
   
    //根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。    
     Object getBean(String name, Class requiredType) throws BeansException;    
    
    //提供对bean的检索,看看是否在IOC容器有这个名字的bean    
     boolean containsBean(String name);    
    
    //根据bean名字得到bean实例,并同时判断这个bean是不是单例    
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;    
    
    //得到bean实例的Class类型    
    Class getType(String name) throws NoSuchBeanDefinitionException;    
    
    //得到bean的别名,如果根据别名检索,那么其原名也会被检索出来    
   String[] getAliases(String name);    
   
   //判断给出的 bean name 是否满足
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

   //判断指定的 的 bean name 和 类型是否匹配,spring使用这个接口,而不是用 instanceof 来进行判断,且判断的对象是 spring中的 bean实例,这个很常用 
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    
 }
  • 这个接口定义了如何获取到容器里面的bean,而工厂自身如何实例化,工厂如何获得这些bean,由子类自己去实现.
  • SimpleJndiBeanFactory:支持jndi,2.5添加,允许
  • AutowireCapableBeanFactory:定义了bean的装配规则接口。
  • HierarchicalBeanFactory:支持层次结构,可以配置parentBeanFactory,ConfigurableListableBeanFactory实现了HierarchicalBeanFactory,提供了可配置功能。
  • ListableBeanFactory:支持枚举

具体的实现,可以通过查看源码获得其设计意义.但总体来说,可以这么理解,
这三个接口( )共同定义了 Bean 的集合 (list) 、Bean 之间的关系 (parent) 、以及 Bean 行为 (wire).

ApplicationContext

ApplicationContext应用上下文,它作为容器的高级形态而存在,除了BeanFactory的基本功能,还提供了更多丰富的功能,常用的有ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext。

image.png

bean的解析可以通过 xml 去定义,例如常用的spring 项目中使用 xml 中的 <bean id="">标签定义.也可以通过注解,配包扫描进行bean解析.

web项目的IOC初始化流程

1.)Resource定位;指对BeanDefinition的资源定位过程。通俗地讲,就是找到定义Javabean信息的XML文件,并将其封装成Resource对象。

2.)BeanDefinition的载入;把用户定义好的Javabean表示为IoC容器内部的数据结构,这个容器内部的数据结构就是BeanDefinition。

3.)向IoC容器注册这些BeanDefinition。

AbstractApplicationContext#reFresh() 方法

在Spring项目启动中,会调用到refresh( ) 方法

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            /**
             * 设置启动时间,设计容器激活标志(active=true)
             * 初始化 properties 资源
             * 验证必须存在的properties(validateRequiredProperties)
             * 初始earlyApplicationEnvents.用于收集已经产生的ApplicationEnvents.
             */
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            /**
             * 调用子类的refeshBeanFactory(),SpringBoot中采用默认的实现,
             * 设置BeanFactory的SerializationId,设置refreshed标志为true。
             * 获取BeanFactory
             * XmlWebApplicationContext ,AnnotationConfigApplicationContext 会在这一步加载BeanDefinition
             */
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            /**
             * 为接下来 context 上下文使用 beanFactory 做一些准备
             * 为BeanFactory 做些标准的设置
             *
             * 为内部的BeanFactory设置类加载器
             *
             * 设置表达式解析器,属性编辑器。
             *
             * 注册BeanPostProcessor(ApplicationContextAwareProcessor,ApplicationListenerDetector),
             *
             * ApplicationContextAwareProcessor:对Spring 中各种Aware接口的支持,在初始化Bean前,调用Bean实现的Aware接口方法。
             * ApplicationListenerDetector:用于收集实现了ApplicationListener接口的Bean
             * 注册指定的依赖类型和对应的value,
             *
             * 例如:beanFactory.registerResolvableDependency(ResourceLoader.class, this);那么在类中自动注入ResourceLoader类型的对象,就会拿到当前IOC容器。
             * 注入一些其它信息的bean,比如environment、systemProperties等
             */
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                /**
                 * 用于子类BeanFactory 完成标准的初始化之后修改BeanFactory。
                 * 不同容器根据自己的需求重写 postProcessBeanFactory 方法,来添加特殊的后置处理器,
                 */
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                /**
                 * 实例化并且执行所有已经注册到BeanFactory中的 BeanFactoryPostProcessor。支持按照Order排序
                 */
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                /**
                 * 注册所有拦截bean创建的bean处理器
                 * todo 这里没搞懂
                 */
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                /**
                 * 初始化一些国际化的属性
                 */
                initMessageSource();

                // Initialize event multicaster for this context.
                /**
                 * 在容器中初始化Application事件广播器。
                 */
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                /**
                 * 子类可以使用 onRefresh 方法,实例化一些自己需要的特定的beans
                 */
                onRefresh();

                // Check for listener beans and register them.
                /**
                 * 将所有的 ApplicationListener 实现类注册 到 ApplicationEventMulticaster中,觉得是观察者模式。
                 * 把已经产生的事件广播出去。
                 */
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons./**
                /**
                 * 实列化所有 非懒加载的 类。
                 */
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                /**
                 * 完成容器的初始化过程,发布相应事件。
                 * 启动容器的声明周期处理器。管理容器声明周期。
                 * 发布 ContextRefreshedEvent事件。
                 * 启动内嵌的Servlet容器。
                 * 发布容器启动事件。
                 */
                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...
                resetCommonCaches();
            }
        }
    }

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这行代码表示获得一个BeanFactory,进入方法里面,可以看到有一个reFreshBeanFactory,然后return getBeanFactory方法

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        return getBeanFactory();
    }

//refreshBeanFactory这个方法是一个抽象方法,委托给了子类去实现
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

查看其子类实现 AbstractRefreshableApplicationContext#refreshBeanFactory()

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            //销毁beans
            destroyBeans();
            //关闭bean工厂
            closeBeanFactory();
        }
        try {
            // new 一个 DefaultListableBeanFactory,这个beanFactory 会设置parentFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            //设置 factory id
            beanFactory.setSerializationId(getId());
            /**
         * 定制化beanFactory
         * 设置两个属性:
         * 1. 是否允许覆盖同名称的不同定义的对象
         * 2. 是否允许bean之间存在循环依赖
         */
            customizeBeanFactory(beanFactory);
            //初始化DocumentReader,并进行XML文件读取和解析
            loadBeanDefinitions(beanFactory);
            //设置 锁点
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

查看 AbstractRefreshableApplicationContext#createBeanFactory( ),返回了一个DefaultListableBeanFactory

protected DefaultListableBeanFactory createBeanFactory() {       
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
  }

AbstractRefreshableApplicationContext#customizeBeanFactory 方法

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {       if (this.allowBeanDefinitionOverriding != null) {             beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);       }       if (this.allowCircularReferences != null) {             beanFactory.setAllowCircularReferences(this.allowCircularReferences);       }}


AbstractRefreshableApplicationContext#loadBeanDefinitions( )
初始化DocumentReader,并进行XML文件读取和解析,由子类实现

    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException;
    

至此,bean工厂的实例化已经完成,但整个初始化在AbstractApplicationContext#refreshBeanFactory()完成后,就会返回一个初始化好的bean工厂,接下来的代码在AbstractApplicationContext#refresh 代码中,会对bean工厂进行上下文,bean后置处理器,用户自定义bean后置处理器,默认bean注册等一系列操作
比如:


    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        /**
         * 为bean工厂加入当前上下文的类加载器
         * 设置表达式解析器
         * 设置资源文件解析器
         */
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        /**
         * 为bean工厂添加后置处理器 ApplicationContextAwareProcessor:对Spring 中各种Aware接口的支持,
         * 在初始化Bean前,调用Bean实现的Aware接口方法
         * 为bean工厂设置 某些 class 不需要加入到 bean 中(因为这些bean可能已经被提前加入)
         */
        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.
        /**
         * 为 bean工厂注册一些特别的用于依赖的bean,比如,在类中需要自动注入ResourceLoader类型的对象,就会拿到当前IOC容器,
         */
        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.
        /**
         * 为bean工厂添加后置处理器 ApplicationListenerDetector:
         * 用于收集实现了ApplicationListener接口的Bean
         */
        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()));
        }

        // Register default environment beans.
        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());
        }
    }

但总体来说,都是对bean工厂进一步增强和丰富。直到 AbstractApplicationContext#refresh完成,那么,bean工厂就初始化完成了,IOC容器的初始化也完成了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。