zoukankan      html  css  js  c++  java
  • 01-Spring概述(总览)

    Spring概述

    前言

    Spring 发展至现在,俨然成为一个生态,但要理解其余的 Spring Boot、Spring Cloud 等框架,需要先对 Spring 的整个体系有一定的理解,因为其余的框架都是在 Spring 框架的基础上进行的扩展,当理解了 Spring 的核心之后其余的框架就很容易搞明白了,Spring 的核心在于 IOC 和 BeanDefinition,IOC容器用于存放所有的单例 Bean 和所创建单例 Bean 所需要的 BeanDefinition,其余的 AOP、事务等全部都是在此基础上进行的扩展。

    此系列可能会将整体混合书写,比如:在进行 Spring 分析的时候,可能会插入一些 Spring Boot 的解析,也有可能会插入别的知识点,但大部分都不会脱离 Spring 源码的主线。

    XML 的方式属于 Spring 的原生使用方式,在后期的时候扩展出了注解方式的处理,文章会从 xml 方式开始,中间会穿插注解的处理方式。其余的很多东西,大家都能在网上查到响应的资料,这里就不再过多的说明。

    这里说一下整体的阅读源码的方式吧,Spring 源码前前后后翻了将近 5-6 次,最近才领略到 Spring 的魅力之所在,大致方式为先整体后细分,先全局再部分,先知道大致的一个处理流程,然后再去看其详细的部分,整个系列也是这个方式,会有一个全局的大流程贯穿,然后辅以详细的流程处理,一层一层的去看里面的处理方式。

    在进行之前,建议安装一个 Translation 翻译插件,方便进行翻译。

    环境搭建问题,这里不再赘述,网上有大量的教程,有问题的话,可以直接进入文章最后的群进行询问。

    注意:这里假设是你已经有一定的开发经验了,很多细小的问题,可能没有注意到,如果有什么疑问,可以直接通过评论或者加群询问。

    IOC总览

    这里的分析主要从 ClassPathXmlApplicationContext 这个类开始,最终会调用到 refresh() 这个方法,整体会从 refresh() 这个方法作为入口进行一系列的分析,其余的 Spring Boot (AnnotationConfigServletWebServerApplicationContext) 框架,等都会调用到这个方法,所以说 refresh() 是核心方法也不为过,所以整体的脉络也不会偏离 refresh() 这个方法。

    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    

    此处,的 super(parent) 会调用父类的方法,加载资源解析器,

    public AbstractApplicationContext() {
        // 创建资源模式处理器,后续在加载 xml 配置文件的时候需要使用到 PathMatchingResourcePatternResolver
        this.resourcePatternResolver = getResourcePatternResolver();
    }
    

    setConfigLocations(configLocations)获取系统属性和系统环境变量,对上述路径进行表达式(${})进行解析。

    public ClassPathXmlApplicationContext(
        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {
        // 调用父类构造方法,进行相关的对象创建等操作,包含属性的赋值操作
        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }
    

    refresh()方法的核心处理

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            	/**
    			 * 做容器刷新前的准备工作
    			 * 1、设置容器的启动时间
    			 * 2、设置活跃状态为true
    			 * 3、设置关闭状态为false
    			 * 4、获取Environment对象,并加载当前系统的属性值到Environment对象中
    			 * 5、准备监听器和事件的集合对象,默认为空的集合
    			 */
    
            prepareRefresh();
    
            	/**
    			// Tell the subclass to refresh the internal bean factory.
    			// 创建容器对象:DefaultListableBeanFactory
    			// 加载xml配置文件的属性值到当前工厂中,最重要的就是 BeanDefinition 加载、解析 xml, 形成 GenericBeanDefinition, 自定义标签的解析和默认的 bean 标签解析都在此处,解析自定义标签的时候会将 inner 类注入到 BeanDefinitionMap 中去
    			 */
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            // Prepare the bean factory for use in this context.
            // beanFactory的准备工作,对各种属性进行填充
            /** 添加一些 BeanPostProcessor,忽略某些接口,添加 SPEL 表达式解析器,注册某些特定的 bean 到 IOC 容器中去*/
            prepareBeanFactory(beanFactory);
    
            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的
                postProcessBeanFactory(beanFactory);
    
                // Invoke factory processors registered as beans in the context.
           /**注册并调用所有的 BFPP 接口,注解的解析就是在此进行,ConfigurationClassPostProcessor 用于解析注解。*/
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // Register bean processors that intercept bean creation.
                // 注册bean处理器,这里只是注册功能,真正调用的是getBean方法
                registerBeanPostProcessors(beanFactory);
    
                // Initialize message source for this context.
                // 为上下文初始化message源,即不同语言的消息体,国际化处理,
                initMessageSource();
    
                // Initialize event multicaster for this context.
                // 初始化事件监听多路广播器
                initApplicationEventMulticaster();
    
                // Initialize other special beans in specific context subclasses.
                // 留给子类来初始化其他的bean
                onRefresh();
    
                // Check for listener beans and register them.
                // 在所有注册的bean中查找listener bean,注册到消息广播器中
                registerListeners();
    
                // Instantiate all remaining (non-lazy-init) singletons.
                // 初始化剩下的单实例(非懒加载的)
                finishBeanFactoryInitialization(beanFactory);
    
                // Last step: publish corresponding event.
                // 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出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.
                // 为防止bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件bean
                destroyBeans();
    
                // Reset 'active' flag.
                // 重置active标志
                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();
            }
        }
    }
    

    整体的大致流程图

    prepareRefresh()

    准备刷新

    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());
    			}
    		}
    
    		// Initialize any placeholder property sources in the context environment.
    		// 留给子类覆盖,初始化属性资源
    		initPropertySources();
    
    		// Validate that all properties marked as required are resolvable:
    		// see ConfigurablePropertyResolver#setRequiredProperties
    		// 创建并获取环境对象,验证需要的属性文件是否都已经放入环境中
    		getEnvironment().validateRequiredProperties();
    
    		// Store pre-refresh ApplicationListeners...
    		// 判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到此集合中
    		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<>();
    	}
    

  • 相关阅读:
    计算机图形学的学习资源
    Matlab绘图基础
    Matlab绘图函数一览
    Matlab编程基础
    Python实现对文件夹内文本文件递归查找
    C++预处理详解
    C++的学习资源
    OGRE启动过程详解(OGRE HelloWorld程序原理解析)
    Bullet核心类介绍(Bullet 2.82 HelloWorld程序及其详解,附程序代码)
    windows下Bullet 2.82编译安装(Bullet Physics开发环境配置)
  • 原文地址:https://www.cnblogs.com/ice-image/p/14502210.html
Copyright © 2011-2022 走看看