天天看点

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

前言

上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。

1.轻描淡写的来一张Spring结构图

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

这些模块可以总结为以下几部分:

1.1 Core Container

Core:Container为核心容器,包含有Core、Beans、Context和Expression  Language模块。

其中,Core模块和Bean模块是Spring框架的基础部分,主要实现了控制反转(IOC)的依赖注入(DI)功能。

(1)Core模块主要包含Spring框架基本核心工具,Spring的其他组件都要用到这个包里的工具类。

(2)Beans模块是所有应用都要应用到的,包含访问和配置文件、创建和管理bean以及进行 Inversion of Control/Dependency Injection(Ioc/DI)操作。

(3)Context模块构建与Core和Beans模块基础之上,提供了一种类似于JNDI的注册器框架式的对象访问方法。Context继承了Beans的特性,为Spring核心提供了大量扩展,添加了国际化、时间传播、资源加载和对Context的透明创建的支持。

(4)Expressionn Languag模块提供了强大的表达式语言,用于在运行时查询和操作对象。

w3school中这样描述:https://www.w3cschool.cn/tomcat/4xy31k9e.htmlJNDI提供了一种统一的方式,可以用在网络上查找和访问服务。通过指定一个资源名称,该名称对应于数据库或命名服务中的一个记录,同时返回数据库连接建立所必须的信息。其实说白了JNDI就是提供一种映射。通过资源名映射到实际的配置。
           

1.2 Data Access/Integration

Data Access/Integration曾包含JDBC、ORM、OXM、JMS和Transaction模块。

(1)JDBC模块提供了一个JDBC抽象层,封装了Spring对JDBC进行数据访问的所有类。

(2)ORM为对象关系映射层。

(3)JMS模块主要包含了一些制造和消费消息的特性。

(4)Transcation模块支持编程和声明式事务管理,这些事务类必须实现特定的接口,并且对所有的POJO透明。

1.3 Web

Web模块是建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文,提供了基础的面向Web的集成特性。例如,文件上传等。

1.4 AOP

AOP模块提供了一个符合AOP联盟标准的面向切面编程的实现,它可以让你在任何地方定义拦截器和切点。

1.5 Test

Test模块支持使用JUit和TestNG对Spring组件进行测试。

2. 从一个简单的例子开始

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图
spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图
spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

 相信这个简单的例子只要有一点开发经验的同学都能够看出来。

 首先,把XMl文件使用classPathResource封装成Resource。

  然后,将Resource传入到XmlBeanfactory进行解析,形成Beanfactory。

 最后,通过Beanfactory获取XML文件中配置的实例化类信息。

 主要过程可以分为:

(1)XML封装成Resource.

(2)Resource进行XmlBeanFactory解析,形成BeanFactory。

(3)从BeanFactory获取实例化好的类。

 到这里Spring主要的核心功能就讲完了,简单吧!

 真的就这么简单吗???

3.来看看XmlBeanFactory标签解析的过程

在正式开始之前先来看看Bean的两个核心类介绍DefaultListableBeanFactory和XmlBeanDefinitioReader。

3.1 DefaultListableBeanFactory

XmlBeanFactory继承自DefaultListableBeanfactory,而DefaultListableBeanfactory是整个Bean加载的核心部分,是Spring注册和加载Bean的默认实现,而对于XmlBeanfactory与DefaultListableBeanfactory不同的是,XmlBeanfactory使用了自定义的XML读取器XmlBeanDefinitionReader,实现了个性能化的BeanDefinionReader读取。通过下图可以清晰的了解到DefaultListableBeanFactory的继承结构,简单的介绍下各个组件结构与功能:

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(1)AliasRegistry:定义alias的简单增删改等操作。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(2)SimpleAliasRegistry:SimpleAliasregistry主要使用aliasMap作为alias的缓存,并对接口AliasRegistry进行实现。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(3)SingletonBeanRegistry:定义对单例的注册以及获取。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(4)BeanFactory: BeanFactory定义Bean以及各种Bean的属性。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(5)DefaultSingletonBeanRegistry:对接口SingletonBeanRegistry函数的实现。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(6)BeanDefinitionRegistry:是对BeanDefiition的各种增删改操作。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(7)FactoryBeanRegistrySupport :在DefaultSinngletonBeanRegistry基础上增加了对FactoryBean的特殊处理功能。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(8)ConfigurableBeanFactory: 提供配置Factory的各种方法。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(9)ListableBeanfactory:根据各种条件获取bean配置清单。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(10)AbstractBeanFactory:综合FactoryBeanRegistrySupport和ConnfigurableBeanFactory 的功能。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(11)AutowireCapableBeanFactory: 提供创建bean、自动注入、初始化以及应用bean后的处理器。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(12)AbstractAutowireCapableBeanFactory:综合AbstractBeanFactory并对接口Autowired Capable  Beanfactory进行实现。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(13)ConfigurableListableBeanFactory: Beanfactor配置清单,制定忽略类型和接口等。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

(14) DefaultListableBeanFactory: 综合上面所有功能,主要是对bean注册后的处理。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

3.2 XmlBeanDefinitionReader

XML文件读取是Spring中重要的功能,因为Spring大部分功能都是以配置作为切入点,可以从XmlBeanDefinitionReader中梳理下资源文件的读取、解析以及注册的大致脉络,先来一张XmlBeanDefinnitionReader继承图。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

1.通过继承自AbstractBeanDefinitionReader中的方法,将ResourcLoader将资源文件转化为对应的Resource文件。

2.通过对DocumentLoader对Resource文件进行转换,将Resource文件转换为Document文件。

3.通过实现接口BeanDefinitionnDocumentReader的DefaultDefinitionCocumentReader类对Document进行解析,并使用BeanDefinitionParseDelegate对Element进行解析。

SAX是什么?SAX(simple API for XML)是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析,但任何事物都有其相反的一面,对于SAX来说就是操作复杂。
           

3.3 XmlBeanFactory

XmlBeanFactory对DefaultListableBeanfactory类进行扩展,主要是从XML文档中读取BeanDefinition。

BeanFactory bf=new XmlBeanfactory(new ClassPathResource("beaFactory.xml"));
           

在上面代码执行过程中,首先调用ClassPathResource的构造函数来构造Resource资源文件的实例对象。这样后续的资源就可以用Resource提供各种资源服务了。当有了Resource后就可以进行XmlBeanFactory的初始化了。那么,问题来了,Resource资源是如何封装的?

Spring配置文件读取时通过ClassPathResource("beanFactoryTest.xml")

在java中,将不同来源的资源抽象成URL,通过注册不同的handler来处理不同资源读取逻辑,一般handler的类型使用不同前缀(协议,Protocol)来识别。,如“file”,"http"."jar"等,然而URL没有默认定义相对Classpath  ServletContext等资源的handler,虽然可以自定义URLStreamHandler来解析特定URl前缀,比如“classpath”然而这需要了解URL机制,而且URL也没有提供基本的方法,如检查当前资源是否存在等方法。因此Spring对其内部使用到的资源 实现了自己的抽象,Resource接口封装底层资源。

Resource可以对所有资源问你件进行统一处理。至于实现,其实非常简单,以getInputStream为;例,CalssPathResource中实现方式便是通过class或者classLoader提供的底层方法进行调用。

有了Resource接口便可以对所有资源文件进行统一管理,实现方式也非常简单,如getInputStram为例,ClassPathResource的实现方式是通过class或者classloader提供的底层方法进行调用,对于FileSystemResource的实现方式更简单,直接使用FileInputStream对文件进行实例化。

了解了Spring将配置文件封装为Resource类型的实例方法后,就开始进行beanDefinition的解析过程,这里分析使用的是Resource作为构造函数对传入参数的解析过程。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

this.reader.loadBeanDefinitions(resource);才是资源加载的真正实现,也是重点分析之一,来看一份时序图。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

首先,封装资源文件,XmlBeanDefinitionReader对参数Resource使用EncodedResource进行封装。然后,获取输入流从Resource中获取相应的InputStream并构造InputSource。最后,通过构造的InputSource实例和Resource实例继续调用函数doLoadBeanDefinitions,doloadBeanDefinition主要做了三件事。(1)获取XML文件的验证模式

(2)加载XML文件,并得到对应的Document.

(3)根据返回的Document注册Bean

3.3.1  XML文件的验证模式

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图
spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

getValidationModeForResource主要是验证XML了文件的正确性

(1)DTD

DTd(Document Type Definnnnition)即文档定义类型,是一种XML约束模式语言,是XML文件的验证 机制,属于XML文件组成的一部分。

(2)XSD

XML Schema(XML Schema Definition)描述了XML文件结构,可以用一个指定的XMLschema来验证某个XML文档,检查XML文档是否符合要求。

3.3.2 Document解析

经过了验证模式准备步骤就可以进行Document加载了,DocumentLoader定义了对Document解析的一些方法,具体的实现类是dafaultDocumentLoader,也是使用SAX解析。

SAX解析XML文档的套路大致都查案不多,Spring在这里没有什么特殊的地方,首先创建DocumentBuilderFactory,再通过DocumentBuilderFactory创建DocumentBuilder,进而解析inputSource来返回Document对象。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

在loadDocument的方法中设计到有一个参数——EntityResolver,那么EntityResolver的作用是什么?由于DTD的资源在网络上,但是由于某些原因可能会出现网络抖动,会延迟DTD资源的加载,我们可以把DTD资源提前下载好存放到enntityResolver中在实现时直接将此文档读取返回SAX即可。这样就避免了通过网络来寻找相应的声明。 3.3.3 Bean注册

当把文件转换为Document后,接下来的提取以及注册bean,当程序已经拥有XML文档文件的Documennt实例对象时,就会引入下面这个方法:

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

preProcessXml和postProcessXml是两个空方法,这两个方法是为子类而设计的,如果对模板模式比较熟悉的话,可以看出这就是用的模板方法。

parseBeanDefinnitionn(root,this.delegate)

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

Spring的XML配置有两大类Bean声明,一个是默认的,如

"test" class="test.Testbean">
           

另一类定义是: 这两种方式的读取以及解析差别是非常大的,根节点或者子节点如果默认是自定义的,那么需要实现一些接口以及配置,对于根节点和子节点如果是默认命名空间的话则采用parseDefaultElement的方法进行解析。否则使用delegate.parsseCustomElement方法对自定义命名空间进行解析。

好了,Spring基本的功能结构和加载过程就先讲解到这,下一期接着讲讲Spring默认标签的解析过程。本文写作过程参考了郝佳大佬的《Spring源码深度解析》,非常感谢。

最近胖虎我新交了一个朋友,爆个照来给大家认识下。

spring容器_Spring容器的基本功能实现前言上次给胖子老板老板讲解完自动问答系统的原理后,获得了胖子老板的高度赞赏,正在满心欢喜的时候,胖老板突然又问我,你知道系统中用到的Spring是什么原理吗? 我回答Spring不是春天的意思吗?……..(此时双方沉默了两分钟)。胖老板说,回去吧…….. 经过本喵的彻夜苦读,终于总结出来Spring以下内容。1.轻描淡写的来一张Spring结构图

继续阅读