画布 1
Spring
  Spring
    Spring Framework
      什么是Spring
      Spring的优缺点
      Spring主要有哪些模块
      Spring主要使用了哪些设计模式
      BeanFactory 和 ApplicationContext 区别
        BeanFactory
        ApplicationContext
      什么是IOC容器和DI依赖注入
      Spring依赖注入的方式有哪些
        构造器
        Setter方法
      Spring有几种配置方式
      一个Bean定义了什么
      Spring有几种Bean的作用域
        singleton
        prototype
        request
        session
        application
        websocket
      Spring 的扩展点主要有哪些
        1. BeanFactoryPostProcessor
        2. 实例化bean
        3. bean实例注入属性
        4. Aware
        5. BeanPostProcessor
        6. InitializingBean / init方法
        7. BeanPostProcessor
        8. bean实例可以被使用了
        9. DisposableBean / destroy 方法
      Spring如何解决循环依赖
        构造器注入无法解决循环依赖
        Setter方法注入依靠三级缓存解决依赖
        非单例bean不能缓存，无法解决循环依赖
      事务的传播行为是什么
        REQUIRED
        REQUIRES_NEW
        NESTED
        SUPPORTS
        MANDATORY
        NOT_SUPPORTED
        NEVER
      什么是AOP
      AOP有哪些组成元素和概念
        连接点
        切入点
        通知/增强
        织入
        切面
      AOP实现方式
        代理
        织入
      AspectJ AOP 和 Spring AOP 区别
        AspectJ
        Spring AOP
      cglib和jdk的区别
        cglib
        jdk
    SpringMVC
      MVC 是什么 / 有什么优点
      什么是 Spring MVC
      Spring MVC的优缺点
      什么是DispatcherServlet
      Spring MVC有哪些组件
        MultipartResolver
        LocalResolver
        ThemeResolver
        ViewResolver
        HandlerExceptionResolver
        HandlerMapping
        HandlerAdapter
        RequestToViewNameTranslator
        FlashMapManager
      简述SpringMVC 原理/执行流程
      Spring MVC 拦截器是什么 / 有什么作用 / 与 Filter有什么区别
      @Component @Controller @Service @Repository 区别
    SpringBoot
      什么是SpringBoot
      SpringBoot的优缺点
        优点
          容易上手，编码简单
          内嵌Web容器
          开箱即用，习惯大于配置
          天然集成SpringCloud微服务
        缺点
          易学难精
      SpringBoot的核心注解是哪个
      Java API配置的优点
      SpringBoot自动配置原理
      SpringBoot配置文件加载顺序
      SpringBoot 怎么切换生产环境和开发环境配置
      SpringBoot是如何推断应用类型和main的
作者: qsjzwithguang19forever
作者微信: yg1446125917
作者邮箱: 2196927727@qq.com
作者github: github.com/guang19
本xmind归属于qsjzwithguang19forever的开源项目:framework-learning。
framework-learning旨在为Java方向的开发者提供较为全面，通俗的知识梳理。
项目地址: github.com/guang19/framework-learning
如若转载，请声明来源。
Spring是一个轻量级的，开源的Java应用程序开发框架。它提供的IOC和AOP等核心功能，能够使开发者很方便的开发出松耦合的应用
Spring的优点:
1. 方便解耦，简化开发
对象统一交由容器管理，实现了资源的可配置和易管理。并且不再需要显示的编写管理对象的代码，降低了应用的代码量。
2. AOP支持
Spring 提供 AOP模块，能够很方便的编写出AOP程序.
3. 声明式事务
只需要通过配置或注解就可以完成对事务的支持，而不需要手动的编写事务代码
4 . 第三方框架无缝集成
Spring可以很方便的将第三方框架继承到系统中，很灵活。
Spring的缺点:
1. 复杂
Spring发展到现在，确认有些复杂了，但是对于它解决的问题来说，复杂已经不算什么了。
2. 效率
Spring内部依赖反射，而反射会带来一定的效率损耗。
1. core模块提供IOC和DI等核心功能
2.aop模块提供面向切面编程的实现
3. web模块提供对web应用的支持
4. dao模块提供数据库方面的支持
5. test模块提供测试方面的支持
1. 工厂模式
BeanFactory 就是简单工厂的实现，用来创建和获取Bean
2. 单例模式
Spring容器的Bean默认是单例的
3. 代理模式
aop使用的就是代理模式
4. 模板方法模式
jdbcTemplate等类就使用模板方法模式
5. 观察者模式
当有事件触发时，该事件的监听者(观察者)就会做出相应的动作。
...
BeanFactory是最底层，最顶级的IOC容器接口，它提供了对bean的基本操作，属于低级容器。
而ApplicationContext是BeanFactory的应用扩展接口，提供了比BeanFactory更多高级的功能和扩展接口，属于高级容器。
IOC(Inversion Of Control)：控制反转.
DI(Dependencies Inject):依赖注入.
Spring IOC容器是Spring框架的核心功能，它负责管理用户定义好的bean以及bean的生命周期，包括(创建，初始化,使用和销毁)，而依赖注入是处理bean与bean之间的依赖关系。
控制反转是指原本由用户来管理对象，现在交由容器管理，不再需要我们手动去处理对象之间的依赖关系了。
构造函数的每个参数都可以代表对其他bean的依赖。
在通过无参构造器或工厂实例化bean后，可以通过bean的setter方法设置bean的属性依赖。
1. 注解
2. Java配置
3. XML配置
BeanDefinition 是对Bean的定义，它定义了Bean的元数据，如Bean的Scope，Class，beanName，bean的实例化方式等等。
singleton(单例bean):
singleton作用域表示在容器中，一个bean只存在一个实例。每次获取这个bean，都是获取它唯一的实例。
prototype(原型bean)
prototype作用域表示如果有一个bean是prototype scope,那么每次获取该作用域的bean时，容器都会新创建该bean的实例。
request(请求域)
作用于Web应用。request作用域表示如果一个bean是request scope，那每次HTTP请求，容器都会创建一个该bean的实例。
session(会话域)
作用与Web应用。session作用域表示如果一个bean是session scope，那么容器为每个session创建一个该bean的实例，当session销毁时，该session内的bean也就销毁了。
application(web应用作用域)
作用与web应用。application作用域表示如果一个bean是 application scope的，那么容器会为整个Web应用上下文创建一个该bean的实例，这个实例属于ServletContext级别的。
不同于singleton，singleton是Spring的每个ApplicationContext唯一，而application是每个ServletContext唯一，对于Web应用来说，ServletContext也只有一个，所以application可以理解为web应用唯一。
websocket(websocket作用域)
应用于web应用。websocket作用域表示如果一个bean是websocket scope的，那么该bean作用域整个WebSocket作用域内，也是唯一的。
这里列举的并不是很全，因为Spring的扩展点实在是太多了，但究其根本，还是在bean实例化前后的扩展。
如果容器中有BeanFactoryPostProcessor 那么执行它的postProcessBeanFactory方法。
该接口是对ConfigurableListableBeanFactory的一个扩展。
如果容器中有Aware的实现，那么执行各种Aware扩展实现方法,如BeanNameAware,BeanFactoryAware,
ApplicationContextAware等扩展的setXXX方法
如果容器中有BeanPostProcessor，那么执行BeanPostProcessor的postProcessBeforeInitialization方法。
执行bean指定的init方法,如果bean还实现了InitializingBean接口,那么继续执行InitializingBean的afterPropertiesSet方法。
如果容器中有BeanPostProcessor，那么执行BeanPostProcessor的postProcessAfterInitialization方法。
容器销毁后，执行bean指定的destroy方法，如果bean还实现了DisposableBean接口，那么继续执行DisposableBean的destroy方法
循环依赖是指:A依赖B，并且B依赖A的情况。或者 A依赖B，B依赖C，C依赖A的情况。
构造器注入的循环依赖无法解决，直接抛出BeanCurrentlyInCreationException异常。
容器在创建Bean的时候，会将Bean添加到正在创建的Bean池中，如果在创建Bean的时候，发现自己已经在创建的Bean池中，就说明Bean陷入循环依赖了，直接抛出BeanCurrentlyInCreationException异常。
为什么构造器注入不能像Setter方法注入一样解决循环依赖问题?
因为Setter方法注入的前提是首先需要实例化这个对象，而构造器注入的参数正是bean啊，怎么实例化，所以无法解决这个问题。
Setter方法注入的循环依赖可以通过缓存解决。
三级缓存：
1). 初始化完成的Bean池；
2). 实例化完成，但是没有填充属性的Bean池；
3). 刚刚实例化完成的Bean的工厂缓存，用于提前曝光Bean。
Setter方法注入时，如果Bean A发现自己依赖于Bean B，那么将自己实例化后并添加到第三级缓存(Bean 工厂)，然后再初始化B,检查到B又依赖于A，于是到三级缓存里查询A,那么查询肯定是成功的,于是将A设置为B的属性。那么当A初始化时，发现B已经初始化完成,就可以直接将B设置为A的属性了。
这个过程主要在于A和B并不依赖于构造器注入，只要实例化完成，并添加到缓存，就可以通过setter方法注入。
非单例循环依赖无法解决。
IOC容器是不会缓存非单例bean的，所以无法解决循环依赖问题。
事务的传播行为是Spring提供的对事务增强的一种特性，不属于数据库事务特性。
事务的传播行为描述的是当多个事务同时存在时，这些事务的该如何被处理。
REQUIRED
当一个方法A(REQUIRED)被另一个方法B调用时，如果B没有开启事务，那么A将自己开启事务,独立运行。如果B开启了事务，那么A就加入到B的事务中去，A和B要么同时成功，要么同时失败。
REQUIRE_NEW
当一个方法A(REQUIRE_NEW)被另一个方法B调用时，无论B是否有事务，A都会开启自己的事务，与B的事务互不相干，隔离运行。
NESTED
NESTED与REQUIRED很相似。
如果方法A(NESTED)被另一个方法B调用，如果B没有事务，那么A将自己开启一个事务运行。如果B有事务，那么A将作为B的子事务运行，B失败，A也失败，但是A失败却不影响B。A是作为B的嵌套事务运行的，所以并不会影响B。
SUPPORTS
当一个方法A(SUPPORTS)被另一个方法B调用时，如果B开启了事务，那么A就加入到B的事务中去。如果B没有开启事务,那就正常执行，不开启事务。
MANDATORY
当一个方法A(MANDATORY)被另一个方法B调用时，如果B没有开启事务，那么A将抛出异常。
NOT_SUPPORTED
当一个方法A(NOT_SUPPORTED)被另一个方法B调用时，如果B有事务，那么B的事务将挂起，直到A执行完，B再以事务的方式运行。
NEVER
当一个方法A(NEVER)被另一个方法B调用时，如果B有事务，那么A将抛出异常。
AOP(Aspect Oriented Programming)
面向切面编程，个人认为AOP是一种程序设计思想。在AOP编程中，将系统的核心逻辑和辅助逻辑分离开来，并将通用的辅助逻辑封装成一个模块，提高了代码的重用性和程序的可维护性，降低了系统模块之间的耦合度。
AOP的组成元素有
1. 连接点
2. 通知/增强
3. 切入点
4. 织入
5. 切面
连接点指程序执行的某个位置，能够执行辅助逻辑(通知)。如方法执行前，方法抛出异常时，方法执行完，方法返回后等等，这些点都被称为连接点。
连接点可以看做是一个方法的执行辅助逻辑的不同位置的集合，切入点指的就是这个方法。切入点会匹配 通知/增强 需要作用的类或方法。
通知即增强。通知可以理解为辅助逻辑，就是在连接点要做的事情。
织入是一个概念。它描述的是将切入点的 通知/增强 应用到连接点的过程。
切面是切入点的集合，可以看作是拥有多个切入点的类。
代理分为静态代理和动态代理。
由于静态代理没有动态代理灵活，所以现在几乎都使用动态代理来实现AOP。
以动态代理实现的AOP框架主要有cglib和jdk自带的这2种。
织入可以理解为以操作字节码的方式对class源文件进行修改，从而实现通知/增强。
以织入实现AOP的框架主要有AspectJ。
AspectJ是一整套AOP的工具，它提供了切面语法(切入点表达式)以及织入等强大的功能。Aspect提供文件和注解2种方式来进行AOP编程，并且它允许在编译时，编译后和加载时织入，但是需要使用它特定的ajc编译器才能实现织入这一功能。
Spring AOP吸收了AspectJ的优点，采用了AspectJ的切入点语法以及AspectJ式的注解，但却并未使用AspectJ的一整套工具，而是集cglib和jdk于一体(动态代理)的方式来实现AOP功能，真的很强。
在SpringAOP 中，如果目标类实现了接口，那么默认使用jdk动态代理来实现AOP，如果目标类没有实现接口，那么将使用cglib来实现AOP。
cglib则是使用字节码技术，动态生成目标的子类，以继承的方式来对目标方法进行重写，所以如果方法是final的，那么cglib将无法对方法进行增强。
jdk只提供基于接口式的动态代理来对目标进行增强。
MVC是一种设计模式，遵循 模型(Model),视图(View) 和 控制器(Controller)的架构设计。
MVC的优点很明显: 应用层次分明，职责分明，使得系统的耦合性降低，并有利于系统的维护。
Spring MVC是一个基于Spring框架的轻量级的MVC Web应用框架。
优点：
1. 基于Spring，拥有Spring的所有优点
2.Spring MVC中的组件:角色分明，耦合性低，非常有利于应用的维护。
3. 支持多种视图技术。不仅支持JSP，还支持各种模板视图。
4. 功能特性强大。轻松的文件上传，数据校验与格式转换，异常处理，Restful风格的API等等。
5. 支持前后端分离。
缺点:
1. Spring MVC是基于Spring的，这既是它的优点也是它的缺点，它必须与Spring一起使用，个人认为这应该是它最大的一个限制了。
DispatcherServlet是Spring MVC的核心,可以说SpringMVC就是这个DispatcherServlet，它是一个Servlet，负责拦截所有的请求，并以调用各种组件来对请求进行分发并处理。
核心组件之一，处理文件上传请求。MultipartResolver负责判断普通请求是否为文件上传请求，并将普通请求(HttpServletRequest)解析为文件上传请求(MultipartHttpServletRequest)。
区域解析器。它主要被用于国际化的资源方面的解析
主题资源解析器。SpringMVC允许用户提供不同主题，主题就是一系列资源的集合使用这些主题可以提高用户体验。
核心组件之一，视图解析器。在Handler执行完请求后，ViewResolver将ModelAndView解析成物理视图，并对物理视图进行model渲染。
核心组件之一，异常处理解析器。在Handler执行请求的过程中可能出现异常，HandlerExceptionResolver就负责处理Handler执行请求过程中的异常。
核心组件之一，请求处理器。根据用户的请求来匹配对应的Handler
核心组件之一，Handler适配器。使用Handler处理请求，并返回处理后的视图(ModelAndView)
核心组件之一,请求到视图的转换器。根据Request设置最终的视图名,当Handler执行完请求后，它会将Request解析成视图名。
核心组件之一,在请求进行重定向时，FlashMapManager用于保存请求中的参数。
1. 用户发出的请求被DispatcherServlet拦截.
2. DispatcherServlet使用HandlerMapping根据请求匹配到相应的Handler，handler实际是HandlerMethod对象.
3. DispatcherServlet根据Handler适配合适的HandlerAdapter.
4. HandlerAdapter使用Handler执行请求，并返回ModelAndView
5. 使用RequestToViewNameTranslator和ViewResolver等解析器，解析并渲染ModelAndView，并处理相关异常信息
6. 渲染后的结果反馈给用户。
Spring MVC拦截器是Spring MVC提供的对用户请求的目标资源做出拦截扩展的处理器。它允许在目标方法执行前后以及View渲染后做出处理。
Filter是Servlet提供的过滤器，它会在目标方法执行前后做出拦截处理。
要说Servlet Filter和Spring MVC 拦截器有啥区别，个人认为除了它们提供的拦截时间不同，目的都是相同的，没啥区别。
@Component 声明一个类为IOC容器的组件，会被IOC容器管理
而@Controller,@Service和@Repository则拥有更细分的语义。@Controller通常用于Web应用，被@Controller注解的类，应该作为一个处理请求的控制器。@Service则是声明一个类为Service类，处理业务逻辑。被@Repository注解的类，应该被用于处理与数据库交互和持久化相关的功能。
SpringBoot是Spring开源组织Pivotal为Spring应用提供的一站式解决方案，简化了Spring应用开发的流程，并提供了非常多的相关生态组件，非常强大。
只要学过Spring/SpringMVC，那么就能很快的编写出一个Spring应用。
SpringBoot无需配置外部Servlet容器就可以轻松的编写出Web应用。并且SpringBoot支持多种容器，如Tomcat，Undertow，jetty，netty等。
即使你不做任何配置，也能够跑起来一个HelloWorld。
说SpringBoot开启了Java EE的新时代一点也不为过，但是它为我们带来这么多好处的同时，我们想要真正了解他的全貌，已经是很难了。虽然上手容易，但是SpringBoot的特性之多，恐怕需要很长时间了才能琢磨清楚。
核心注解自然是启动SpringBoot应用的那个注解啦:@SpringBootApplication。它由@SpringBootConfiguration(@Configuration),@EnableAutoConfiguration,@ComponentScan 3个核心注解组成。
@SpringBootConfiguration等同于@Configuration,它声明一个类为配置类。
@EnableAutoConfiguration是SpringBoot自动配置的核心注解，没有它，SpringBoot的自动配置就不会生效
@ComponentScan 容器组件扫描的注解，负责扫描所有的容器组件，也是最核心的注解之一。
Spring应用有三种配置组件的方式:注解，Java API(Java Config)，XML.
其中注解和Java API的组合，完全可以干掉冗余的XML配置。
初学Spring的时候，见得最多的不是某行代码，而是XML配置啊。有的同学恨不得要把Spring的约束文件给背下来了~_~。。
而@Configuration和@Bean的到来，无疑是开启了Spring应用配置方式的另一个时代。
Java配置的最大好处就是配置灵活，编写简单，其次是修改方便。但是个人认为还是有缺点的，因为使用Java配置就意味着你需要创建很多的配置类，如果把所有配置都写在一个类里面，那会变得很难维护，所以较好的选择是不同的配置，创建不同的类，这样易于维护。
XML配置的优点就是很通俗易懂，不然XML语言不可能成为通用的数据传输语言，但是想想一个应用里的配置何其多，这就是它最大的缺点:繁琐。
@EnableAutoConfiguration使得容器会读取类路径下 META-INF/spring.factories 文件，并导入文件中声明的自动配置类。spring.factories里定义的都是扩展组件的自动配置类,这些配置类往往都会依赖于XXXProperties.java的属性类，我们在application.properties/yml文件里配置的属性，就是配置的这些XXXProperties.java类的属性。
1. application.properties
2. application.yml
3. ...
因为springboot优先读取application.properties,所以可以在application.properties中配置spring.profile.active = dev/pro/... 来进行配置文件的切换
在SpringBoot中，有一个WebApplicationType的枚举类定义了3种Web类型:NONE,SERVLET(Servlet 类型),REACTIVE(响应式类型)，SpringBoot在启动时会根据对应类型的类是否存在。
而判断main方法是根据异常堆栈来判断的。