• 小白学java-spring相关知识笔记


    ⼀句话概括:Spring 是⼀个轻量级、⾮⼊侵式的控制反转 (IoC) 和⾯向切⾯ (AOP) 的框架。

    2003 年,⼀个⾳乐家 Rod Johnson 决定发展⼀个轻量级的 Java 开发框架, Spring 作为 Java 战场
    的龙骑兵渐渐崛起,并淘汰了 EJB 这个传统的重装骑兵。

     

    1. IOC DI 的⽀持
    Spring 的核⼼就是⼀个⼤的⼯⼚容器,可以维护所有对象的创建和依赖关系, Spring ⼯⼚⽤
    于⽣成 Bean ,并且管理 Bean 的⽣命周期,实现 ⾼内聚低耦合 的设计理念。
    2. AOP 编程的⽀持
    Spring 提供了 ⾯向切⾯编程 ,可以⽅便的实现对程序进⾏权限拦截、运⾏监控等切⾯功能。
    3. 声明式事务的⽀持
    ⽀持通过配置就来完成对事务的管理,⽽不需要通过硬编码的⽅式,以前重复的⼀些事务提
    交、回滚的 JDBC 代码,都可以不⽤⾃⼰写了。
    4. 快捷测试的⽀持
    Spring Junit 提供⽀持,可以通过 注解 快捷地测试 Spring 程序。
    5. 快速集成功能
    ⽅便集成各种优秀框架, Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架
    (如: Struts Hibernate MyBatis Quartz 等)的直接⽀持。
    6. 复杂 API 模板封装
    Spring JavaEE 开发中⾮常难⽤的⼀些 API JDBC JavaMail 、远程调⽤等)都提供了模板
    化的封装,这些封装 API 的提供使得应⽤难度⼤⼤降低。

    2.Spring 有哪些模块呢?
    Spring 框架是分模块存在,除了最核⼼的 Spring Core Container 是必要模块之外,其他
    模块都是 可选 ,⼤约有 20 多个模块。

    最主要的七⼤模块:
    1. Spring Core Spring 核⼼,它是框架最基础的部分,提供 IOC 和依赖注⼊ DI 特性。
    2. Spring Context Spring 上下⽂容器,它是 BeanFactory 功能加强的⼀个⼦接⼜。
    3. Spring Web :它提供 Web 应⽤开发的⽀持。
    4. Spring MVC :它针对 Web 应⽤中 MVC 思想的实现。
    5. Spring DAO :提供对 JDBC 抽象层,简化了 JDBC 编码,同时,编码更具有健壮性。
    6. Spring ORM :它⽀持⽤于流⾏的 ORM 框架的整合,⽐如: Spring + Hibernate Spring +
    iBatis Spring + JDO 的整合等。
    7. Spring AOP :即⾯向切⾯编程,它提供了与 AOP 联盟兼容的编程实现。

    Web :
    @Controller :组合注解(组合了 @Component 注解),应⽤在 MVC 层(控制层)。
    @RestController :该注解为⼀个组合注解,相当于 @Controller @ResponseBody 的组合,
    注解在类上,意味着,该 Controller 的所有⽅法都默认加上了 @ResponseBody
    @RequestMapping :⽤于映射 Web 请求,包括访问路径和参数。如果是 Restful 风格接⼜,
    还可以根据请求类型使⽤不同的注解:
    @GetMapping
    @PostMapping
    @PutMapping
    @DeleteMapping
    @ResponseBody :⽀持将返回值放在 response 内,⽽不是⼀个页⾯,通常⽤户返回 json
    据。
    @RequestBody :允许 request 的参数在 request 体中,⽽不是在直接连接在地址后⾯。
    @PathVariable :⽤于接收路径参数,⽐如 @RequestMapping(“/hello/{name}”) 申明的路径,
    将注解放在参数中前,即可获取该值,通常作为 Restful 的接⼜实现⽅法。
    @RestController :该注解为⼀个组合注解,相当于 @Controller @ResponseBody 的组合,
    注解在类上,意味着,该 Controller 的所有⽅法都默认加上了 @ResponseBody
    容器 :
    @Component :表⽰⼀个带注释的类是⼀个 组件 ,成为 Spring 管理的 Bean 。当使⽤基于
    注解的配置和类路径扫描时,这些类被视为⾃动检测的候选对象。同时 @Component 还是
    ⼀个元注解。
    @Service :组合注解(组合了 @Component 注解),应⽤在 service 层(业务逻辑层)。
    @Repository :组合注解(组合了 @Component 注解),应⽤在 dao 层(数据访问层)。
    @Autowired Spring 提供的⼯具(由 Spring 的依赖注⼊⼯具( BeanPostProcessor
    BeanFactoryPostProcessor )⾃动注⼊)。
    @Qualifier :该注解通常跟 @Autowired ⼀起使⽤,当想对注⼊的过程做更多的控制,
    @Qualifier 可帮助配置,⽐如两个以上相同类型的 Bean Spring ⽆法抉择,⽤到此注解
    @Configuration :声明当前类是⼀个配置类(相当于⼀个 Spring 配置的 xml ⽂件)
    @Value :可⽤在字段,构造器参数跟⽅法参数,指定⼀个默认值,⽀持 #{} ${} 两个
    ⽅式。⼀般将 SpringbBoot 中的 application.properties 配置的属性值赋值给变量。
    @Bean :注解在⽅法上,声明当前⽅法的返回值为⼀个 Bean 。返回的 Bean 对应的类中可
    以定义 init() ⽅法和 destroy() ⽅法,然后在 @Bean(initMethod=”init”,destroyMethod=”destroy”)
    定义,在构造之后执⾏ init ,在销毁之前执⾏ destroy
    @Scope: 定义我们采⽤什么模式去创建 Bean (⽅法上,得有 @Bean ) 其设置类型包括:
    Singleton Prototype Request Session GlobalSession
    AOP :
    @Aspect: 声明⼀个切⾯(类上) 使⽤ @After @Before @Around 定义建⾔( advice ),
    可直接将拦截规则(切点)作为参数。
    @After :在⽅法执⾏之后执⾏(⽅法上)。
    @Before : 在⽅法执⾏之前执⾏(⽅法上)。
    @Around : 在⽅法执⾏之前与之后执⾏(⽅法上)。
    @PointCut : 声明切点 在 java 配置类中使⽤ @EnableAspectJAutoProxy 注解开启
    Spring AspectJ 代理的⽀持(类上)。
    事务:
    @Transactional :在要开启事务的⽅法上使⽤ @Transactional 注解,即可声明式开启事务。

    1. ⼯⼚模式 : Spring 容器本质是⼀个⼤⼯⼚,使⽤⼯⼚模式通过 BeanFactory
    ApplicationContext 创建 bean 对象。
    2. 代理模式 : Spring AOP 功能功能就是通过代理模式来实现的,分为动态代理和静态代
    理。
    3. 单例模式 : Spring 中的 Bean 默认都是单例的,这样有利于容器对 Bean 的管理。
    4. 模板模式 : Spring JdbcTemplate RestTemplate 等以 Template 结尾的对数据库、⽹络等
    等进⾏操作的模板类,就使⽤到了模板模式。
    5. 观察者模式 : Spring 事件驱动模型就是观察者模式很经典的⼀个应⽤。
    6. 适配器模式 :Spring AOP 的增强或通知 (Advice) 使⽤到了适配器模式、 Spring MVC 中也
    是⽤到了适配器模式适配 Controller
    7. 策略模式 : Spring 中有⼀个 Resource 接⼜,它的不同实现类,会根据不同的策略去访问资
    源。

     

    IOC
    5. 说⼀说什么是 IOC ?什么是 DI?
    Java 是⾯向对象的编程语⾔,⼀个个实例对象相互合作组成了业务逻辑,原来,我们都是在
    代码⾥创建对象和对象的依赖。
    所谓的 IOC (控制反转):就是由容器来负责控制对象的⽣命周期和对象间的关系。以前是
    我们想要什么,就⾃⼰创建什么,现在是我们需要什么,容器就给我们送来什么。
    也就是说,控制对象⽣命周期的不再是引⽤它的对象,⽽是容器。对具体对象,以前是它控
    制其它对象,现在所有对象都被容器控制,所以这就叫 控制反转

    DI (依赖注⼊) :指的是容器在实例化对象的时候把它依赖的类注⼊给它。有的说法 IOC
    DI 是⼀回事,有的说法是 IOC 是思想, DI IOC 的实现。
    为什么要使⽤ IOC 呢?
    最主要的是两个字 解耦 ,硬编码会造成对象间的过度耦合,使⽤ IOC 之后,我们可以不⽤关
    ⼼对象间的依赖,专⼼开发应⽤就⾏。

    6. 能简单说⼀下 Spring IOC 的实现机制吗?
    PS: 这道题⽼三在⾯试中被问到过,问法是 你有⾃⼰实现过简单的 Spring 吗?
    Spring IOC 本质就是⼀个⼤⼯⼚,我们想想⼀个⼯⼚是怎么运⾏的呢?

    Bean 定义:
    Bean 通过⼀个配置⽂件定义,把它解析成⼀个类型。
    beans.properties
    偷懒,这⾥直接⽤了最⽅便解析的 properties ,这⾥直接⽤⼀个 类型的配置来代
    Bean 的定义,其中 key beanName value class
    userDao : cn . fighter3 . bean . UserDao
    BeanDefinition.java
    bean 定义类,配置⽂件中 bean 定义对应的实体
    public class BeanDefinition {
    private String beanName ;
    private Class beanClass ;
    // 省略 getter setter
    }
    ResourceLoader.java
    资源加载器,⽤来完成配置⽂件中配置的加载
    public class ResourceLoader {
    public static Map < String , BeanDefinition > getResource () {
    Map < String , BeanDefinition > beanDefinitionMap = new HashMap <>
    ( 16 );
    Properties properties = new Properties ();
    try {
    InputStream inputStream =
    ResourceLoader . class . getResourceAsStream ( "/beans.properties" );
    properties . load ( inputStream );
    Iterator < String > it =
    properties . stringPropertyNames (). iterator ();
    while ( it . hasNext ()) {
    String key = it . next ();
    String className = properties . getProperty ( key );
    BeanDefinition beanDefinition = new BeanDefinition ();
    beanDefinition . setBeanName ( key );
    Class clazz = Class . forName ( className );
    beanDefinition . setBeanClass ( clazz );
    beanDefinitionMap . put ( key , beanDefinition );
    }
    inputStream . close ();
    } catch ( IOException | ClassNotFoundException e ) {
    e . printStackTrace ();
    }
    return beanDefinitionMap ;
    }
    }
    BeanRegister.java
    对象注册器,这⾥⽤于单例 bean 的缓存,我们⼤幅简化,默认所有 bean 都是单例的。可以
    看到所谓单例注册,也很简单,不过是往 HashMap ⾥存对象。
    public class BeanRegister {
    // 单例 Bean 缓存
    private Map < String , Object > singletonMap = new HashMap <> ( 32 );
    /*
    * 获取单例 Bean
    *
    * @param beanName bean 名称
    * @return
    */
    public Object getSingletonBean ( String beanName ) {
    return singletonMap . get ( beanName );
    }
    /**
    * 注册单例 bean
    *
    * @param beanName
    * @param bean
    */
    public void registerSingletonBean ( String beanName , Object bean ) {
    if ( singletonMap . containsKey ( beanName )) {
    return ;
    }
    singletonMap . put ( beanName , bean );
    }
    }

     

    对象⼯⼚,我们最 核⼼ 的⼀个类,在它初始化的时候,创建了 bean 注册器,完成了资
    源的加载。
    获取 bean 的时候,先从单例缓存中取,如果没有取到,就创建并注册⼀个 bean

    7. 说说 BeanFactory ApplicantContext?
    可以这么形容, BeanFactory Spring ⼼脏 ApplicantContext 是完整的 ⾝躯
    BeanFactory Bean ⼯⼚)是 Spring 框架的基础设施,⾯向 Spring 本⾝。
    ApplicantContext (应⽤上下⽂)建⽴在 BeanFactoty 基础上,⾯向使⽤ Spring 框架的开发
    者。
    BeanFactory 接⼜
    BeanFactory 是类的通⽤⼯⼚,可以创建并管理各种类的对象。
    Spring BeanFactory 提供了很多种实现,最常⽤的是 XmlBeanFactory ,但在 Spring 3.2 中已被
    废弃,建议使⽤ XmlBeanDefinitionReader DefaultListableBeanFactory
    BeanFactory 接⼜位于类结构树的顶端,它最主要的⽅法就是 getBean(String var1) ,这个⽅法从
    容器中返回特定名称的 Bean
    BeanFactory 的功能通过其它的接⼜得到了不断的扩展,⽐如
    AbstractAutowireCapableBeanFactory 定义了将容器中的 Bean 按照某种规则(⽐如按名字匹配、
    按类型匹配等)进⾏⾃动装配的⽅法。
    这⾥看⼀个 XMLBeanFactory (已过期) 获取 bean 的例⼦:
    public class HelloWorldApp {
    public static void main( String [] args) {
    BeanFactory factory = new XmlBeanFactory ( new
    ClassPathResource( "beans.xml" ));
    HelloWorld obj = (HelloWorld) factory.getBean( "helloWorld" );
    obj.getMessage();
    }
    }
    ApplicationContext 接⼜
    ApplicationContext BeanFactory 派⽣⽽来,提供了更多⾯向实际应⽤的功能。可以这么说,
    使⽤ BeanFactory 就是⼿动档,使⽤ ApplicationContext 就是⾃动档。
    ApplicationContext 继承了 HierachicalBeanFactory ListableBeanFactory 接⼜,在此基础上,还
    通过其他的接⼜扩展了 BeanFactory 的功能,包括:
    Bean instantiation/wiring
    Bean 的实例化 / 串联
    ⾃动的 BeanPostProcessor 注册
    ⾃动的 BeanFactoryPostProcessor 注册
    ⽅便的 MessageSource 访问( i18n
    ApplicationEvent 的发布与 BeanFactory 懒加载的⽅式不同,它是预加载,所以,每⼀个
    bean 都在 ApplicationContext 启动之后实例化
    这是 ApplicationContext 的使⽤例⼦:

    8. 你知道 Spring 容器启动阶段会⼲什么吗?
    PS :这道题⽼三⾯试被问到过
    Spring IOC 容器⼯作的过程,其实可以划分为两个阶段: 容器启动阶段 Bean 实例化阶
    其中容器启动阶段主要做的⼯作是加载和解析配置⽂件,保存到对应的 Bean 定义中。
    容器启动开始,⾸先会通过某种途径加载 Congiguration MetaData ,在⼤部分情况下,容器需
    要依赖某些⼯具类( BeanDefinitionReader )对加载的 Congiguration MetaData 进⾏解析和分
    析,并将分析后的信息组为相应的 BeanDefinition
    最后把这些保存了 Bean 定义必要信息的 BeanDefinition ,注册到相应的 BeanDefinitionRegistry
    这样容器启动就完成了。

    9. 能说⼀下 Spring Bean ⽣命周期吗?
    可以看看: Spring Bean ⽣命周期,好像⼈的⼀⽣。。
    Spring 中,基本容器 BeanFactory 和扩展容器 ApplicationContext 的实例化时机不太⼀样,
    BeanFactory 采⽤的是延迟初始化的⽅式,也就是只有在第⼀次 getBean() 的时候,才会实例化
    Bean ApplicationContext 启动之后会实例化所有的 Bean 定义。
    Spring IOC Bean 的⽣命周期⼤致分为四个阶段: 实例化 Instantiation )、 属性赋值
    Populate )、 初始化 Initialization )、 销毁 Destruction )。
    我们再来看⼀个稍微详细⼀些的过程:
    实例化 :第 1 步,实例化⼀个 Bean 对象
    属性赋值 :第 2 步,为 Bean 设置相关属性和依赖
    初始化 :初始化的阶段的步骤⽐较多, 5 6 步是真正的初始化,第 3 4 步为在初始化前
    执⾏,第 7 步在初始化后执⾏,初始化完成之后, Bean 就可以被使⽤了
    销毁 :第 8~10 步,第 8 步其实也可以算到销毁阶段,但不是真正意义上的销毁,⽽是先
    在使⽤前注册了销毁的相关调⽤接⼜,为了后⾯第 9 10 步真正销毁 Bean 时再执⾏相应的
    ⽅法

     

     

     

     

    10.Bean 定义和依赖定义有哪些⽅式?
    有三种⽅式: 直接编码⽅式 配置⽂件⽅式 注解⽅式
    直接编码⽅式:我们⼀般接触不到直接编码的⽅式,但其实其它的⽅式最终都要通过直接
    编码来实现。
    配置⽂件⽅式:通过 xml propreties 类型的配置⽂件,配置相应的依赖关系, Spring 读取
    配置⽂件,完成依赖关系的注⼊。
    注解⽅式:注解⽅式应该是我们⽤的最多的⼀种⽅式了,在相应的地⽅使⽤注解修饰,
    Spring 会扫描注解,完成依赖关系的注⼊。
    11. 有哪些依赖注⼊的⽅法?
    Spring ⽀持 构造⽅法注⼊ 属性注⼊ ⼯⼚⽅法注⼊ , 其中⼯⼚⽅法注⼊,又可以分为 静态⼯
    ⼚⽅法注⼊ ⾮静态⼯⼚⽅法注⼊

     

    什么是⾃动装配?
    Spring IOC 容器知道所有 Bean 的配置信息,此外,通过 Java 反射机制还可以获知实现类的结构
    信息,如构造⽅法的结构、属性等信息。掌握所有 Bean 的这些信息后, Spring IOC 容器就可以
    按照某种规则对容器中的 Bean 进⾏⾃动装配,⽽⽆须通过显式的⽅式进⾏依赖配置。
    Spring 提供的这种⽅式,可以按照某些规则进⾏ Bean 的⾃动装配,元素提供了⼀个指定⾃动装
    配类型的属性: autowire="< ⾃动装配类型 >"
    byName :根据名称进⾏⾃动匹配,假设 Boss 又⼀个名为 car 的属性,如果容器中刚好有⼀
    个名为 car bean Spring 就会⾃动将其装配给 Boss car 属性
    byType :根据类型进⾏⾃动匹配,假设 Boss 有⼀个 Car 类型的属性,如果容器中刚好有⼀
    Car 类型的 Bean Spring 就会⾃动将其装配给 Boss 这个属性
    constructor :与 byType 类似, 只不过它是针对构造函数注⼊⽽⾔的。如果 Boss 有⼀个构
    造函数,构造函数包含⼀个 Car 类型的⼊参,如果容器中有⼀个 Car 类型的 Bean ,则 Spring
    将⾃动把这个 Bean 作为 Boss 构造函数的⼊参;如果容器中没有找到和构造函数⼊参匹配类
    型的 Bean ,则 Spring 将抛出异常。
    autodetect :根据 Bean 的⾃省机制决定采⽤ byType 还是 constructor 进⾏⾃动装配,如果 Bean
    提供了默认的构造函数,则采⽤ byType ,否则采⽤ constructor

     

    singleton : Spring 容器仅存在⼀个 Bean 实例, Bean 以单实例的⽅式存在,是 Bean 默认的
    作⽤域。
    prototype : 每次从容器重调⽤ Bean 时,都会返回⼀个新的实例。
    以下三个作⽤域于只在 Web 应⽤中适⽤:
    request : 每⼀次 HTTP 请求都会产⽣⼀个新的 Bean ,该 Bean 仅在当前 HTTP Request 内有
    效。
    session : 同⼀个 HTTP Session 共享⼀个 Bean ,不同的 HTTP Session 使⽤不同的 Bean
    globalSession :同⼀个全局 Session 共享⼀个 Bean ,只⽤于基于 Protlet Web 应⽤, Spring5
    中已经不存在了。

    14.Spring 中的单例 Bean 会存在线程安全问题吗?
    ⾸先结论在这: Spring 中的单例 Bean 不是线程安全的
    因为单例 Bean ,是全局只有⼀个 Bean ,所有线程共享。如果说单例 Bean ,是⼀个⽆状态的,
    也就是线程中的操作不会对 Bean 中的成员变量执⾏ 查询 以外的操作,那么这个单例 Bean 是线
    程安全的。⽐如 Spring mvc Controller Service Dao 等,这些 Bean ⼤多是⽆状态的,只关
    注于⽅法本⾝。
    假如这个 Bean 是有状态的,也就是会对 Bean 中的成员变量进⾏写操作,那么可能就存在线程
    安全的问题。
    单例 Bean 线程安全问题怎么解决呢?
    常见的有这么些解决办法:
    1. Bean 定义为多例
    这样每⼀个线程请求过来都会创建⼀个新的 Bean ,但是这样容器就不好管理 Bean ,不能
    这么办。
    2. Bean 对象中尽量避免定义可变的成员变量
    削⾜适履了属于是,也不能这么⼲。
    3. Bean 中的成员变量保存在 ThreadLocal
    我们知道 ThredLoca 能保证多线程下变量的隔离,可以在类中定义⼀个 ThreadLocal 成员变
    量,将需要的可变成员变量保存在 ThreadLocal ⾥,这是推荐的⼀种⽅式。
    只有单例的 Bean 才存在循环依赖的情况, 原型 (Prototype) 情况下, Spring 会直接抛出异常。原
    因很简单, AB 循环依赖, A 实例化的时候,发现依赖 B ,创建 B 实例,创建 B 的时候发现需要
    A ,创建 A1 实例 …… ⽆限套娃,直接把系统⼲垮。
    Spring 可以解决哪些情况的循环依赖?
    Spring 不⽀持基于构造器注⼊的循环依赖,但是假如 AB 循环依赖,如果⼀个是构造器注⼊,
    ⼀个是 setter 注⼊呢?
    看看⼏种情形:

     

    第四种可以⽽第五种不可以的原因是 Spring 在创建 Bean 时默认会根据⾃然排序进⾏创建,
    所以 A 会先于 B 进⾏创建。
    所以简单总结,当循环依赖的实例都采⽤ setter ⽅法注⼊的时候, Spring 可以⽀持,都采⽤构造
    器注⼊的时候,不⽀持,构造器注⼊和 setter 注⼊同时存在的时候,看天。

    16. Spring 怎么解决循环依赖的呢?
    PS :其实正确答案是开发⼈员做好设计,别让 Bean 循环依赖,但是没办法,⾯试官不想
    听这个。
    我们都知道,单例 Bean 初始化完成,要经历三步:

    注⼊就发⽣在第⼆步, 属性赋值 ,结合这个过程, Spring 通过 三级缓存 解决了循环依赖:
    1. ⼀级缓存 : Map singletonObjects ,单例池,⽤于保存实例化、属性赋值
    (注⼊)、初始化完成的 bean 实例
    2. ⼆级缓存 : Map earlySingletonObjects ,早期曝光对象,⽤于保存实例化完
    成的 bean 实例
    3. 三级缓存 : Map> singletonFactories ,早期曝光对象⼯⼚,⽤于保
    bean 创建⼯⼚,以便于后⾯扩展有机会创建代理对象。

    我们来看⼀下三级缓存解决循环依赖的过程:
    A B 两个类发⽣循环依赖时:

     

     

    A 实例的初始化过程:
    1. 创建 A 实例,实例化的时候把 A 对象⼯⼚放⼊三级缓存,表⽰ A 开始实例化了,虽然我这
    个对象还不完整,但是先曝光出来让⼤家知道

    2. A 注⼊属性时,发现依赖 B ,此时 B 还没有被创建出来,所以去实例化 B
    3. 同样, B 注⼊属性时发现依赖 A ,它就会从缓存⾥找 A 对象。依次从⼀级到三级缓存查询
    A ,从三级缓存通过对象⼯⼚拿到 A ,发现 A 虽然不太完善,但是存在,把 A 放⼊⼆级缓
    存,同时删除三级缓存中的 A ,此时, B 已经实例化并且初始化完成,把 B 放⼊⼀级缓存。

    4. 接着 A 继续属性赋值,顺利从⼀级缓存拿到实例化且初始化完成的 B 对象, A 对象创建也
    完成,删除⼆级缓存中的 A ,同时把 A 放⼊⼀级缓存
    5. 最后,⼀级缓存中保存着实例化、初始化都完成的 A B 对象

     

    所以,我们就知道为什么 Spring 能解决 setter 注⼊的循环依赖了,因为实例化和属性赋值是分开
    的,所以⾥⾯有操作的空间。如果都是构造器注⼊的化,那么都得在实例化这⼀步完成注
    ⼊,所以⾃然是⽆法⽀持了。

    17. 为什么要三级缓存?⼆级不⾏吗?
    不⾏,主要是为了 ⽣成代理对象 。如果是没有代理的情况下,使⽤⼆级缓存解决循环依赖也
    OK 的。但是如果存在代理,三级没有问题,⼆级就不⾏了。
    因为三级缓存中放的是⽣成具体对象的匿名内部类,获取 Object 的时候,它可以⽣成代理对
    象,也可以返回普通对象。使⽤三级缓存主要是为了保证不管什么时候使⽤的都是⼀个对
    象。
    假设只有⼆级缓存的情况,往⼆级缓存中放的显⽰⼀个普通的 Bean 对象, Bean 初始化过程
    中,通过 BeanPostProcessor 去⽣成代理对象之后,覆盖掉⼆级缓存中的普通 Bean 对象,那么
    可能就导致取到的 Bean 对象不⼀致了。

     

     

    19. 说说什么是 AOP
    AOP :⾯向切⾯编程。简单说,就是把⼀些业务逻辑中的相同的代码抽取到⼀个独⽴的模块
    中,让业务逻辑更加清爽。

    我们可以把 ⽇志记录 数据校验 可重⽤的功能模块分离出来,然后在程序的执⾏的合适的地
    ⽅动态地植⼊这些代码并执⾏。这样就简化了代码的书写。

     

    业务逻辑代码中没有参和通⽤逻辑的代码,业务模块更简洁,只包含核⼼业务代码。实现了
    业务逻辑和通⽤逻辑的代码分离,便于维护和升级,降低了业务逻辑和通⽤逻辑的耦合性。
    AOP 可以将遍布应⽤各处的功能分离出来形成可重⽤的组件。在编译期间、装载期间或运⾏
    期间实现在不修改源代码的情况下给程序动态添加功能。从⽽实现对业务逻辑的隔离,提⾼
    代码的模块化能⼒。

     

    AOP 的核⼼其实就是 动态代理 ,如果是实现了接⼜的话就会使⽤ JDK 动态代理,否则使⽤
    CGLIB 代理,主要应⽤于处理⼀些具有横切性质的系统级服务,如⽇志收集、事务管理、安
    全检查、缓存、对象池管理等。
    AOP 有哪些核⼼概念?
    切⾯ Aspect ):类是对物体特征的抽象,切⾯就是对横切关注点的抽象
    连接点 Joinpoint ):被拦截到的点,因为 Spring 只⽀持⽅法类型的连接点,所以在
    Spring 中连接点指的就是被拦截到的⽅法,实际上连接点还可以是字段或者构造器
    切点 Pointcut ):对连接点进⾏拦截的定位
    通知 Advice ):所谓通知指的就是指拦截到连接点之后要执⾏的代码,也可以称作
    ⽬标对象 Target ):代理的⽬标对象
    织⼊ Weabing ):织⼊是将增强添加到⽬标类的具体连接点上的过程。
    编译期织⼊:切⾯在⽬标类编译时被织⼊
    类加载期织⼊:切⾯在⽬标类加载到 JVM 时被织⼊。需要特殊的类加载器,它可以在
    ⽬标类被引⼊应⽤之前增强该⽬标类的字节码。
    运⾏期织⼊:切⾯在应⽤运⾏的某个时刻被织⼊。⼀般情况下,在织⼊切⾯时, AOP
    容器会为⽬标对象动态地创建⼀个代理对象。 SpringAOP 就是以这种⽅式织⼊切⾯。
    Spring 采⽤运⾏期织⼊,⽽ AspectJ 采⽤编译期织⼊和类加载器织⼊。
    引介 introduction ):引介是⼀种特殊的增强,可以动态地为类添加⼀些属性和⽅法
    AOP 有哪些环绕⽅式?
    AOP ⼀般有 5 环绕⽅式:
    前置通知 (@Before)
    返回通知 (@AfterReturning)
    异常通知 (@AfterThrowing)
    后置通知 (@After)
    环绕通知 (@Around)
    多个切⾯的情况下,可以通过 @Order 指定先后顺序,数字越⼩,优先级越⾼。

     

    21. 说说 JDK 动态代理和 CGLIB 代理 ?
    Spring AOP 是通过 动态代理 来实现的,动态代理主要有两种⽅式 JDK 动态代理和 Cglib 动态
    代理,这两种动态代理的使⽤和原理有些不同。
    JDK 动态代理
    1. Interface :对于 JDK 动态代理,⽬标类需要实现⼀个 Interface
    2. InvocationHandler InvocationHandler 是⼀个接⼜,可以通过实现这个接⼜,定义横切逻
    辑,再通过反射机制( invoke )调⽤⽬标类的代码,在次过程,可能包装逻辑,对⽬标⽅
    法进⾏前置后置处理。
    3. Proxy Proxy 利⽤ InvocationHandler 动态创建⼀个符合⽬标类实现的接⼜的实例,⽣成⽬
    标类的代理对象。
    CgLib 动态代理
    1. 使⽤ JDK 创建代理有⼀⼤限制,它只能为接⼜创建代理实例,⽽ CgLib 动态代理就没有这
    个限制。
    2. CgLib 动态代理是使⽤字节码处理框架 ASM ,其原理是通过字节码技术为⼀个类创建⼦
    类,并在⼦类中采⽤⽅法拦截的技术拦截所有⽗类⽅法的调⽤,顺势织⼊横切逻辑。
    3. CgLib 创建的动态代理对象性能⽐ JDK 创建的动态代理对象的性能⾼不少,但是 CGLib
    在创建代理对象时所花费的时间却⽐ JDK 多得多,所以对于单例的对象,因为⽆需频繁
    创建对象,⽤ CGLib 合适,反之,使⽤ JDK ⽅式要更为合适⼀些。同时,由于 CGLib
    于是采⽤动态创建⼦类的⽅法,对于 final ⽅法,⽆法进⾏代理。

    22. 说说 Spring AOP AspectJ AOP 区别 ?
    Spring AOP
    Spring AOP 属于 运⾏时增强 ,主要具有如下特点:
    1. 基于动态代理来实现,默认如果使⽤接⼜的,⽤ JDK 提供的动态代理实现,如果是⽅法
    则使⽤ CGLIB 实现
    2. Spring AOP 需要依赖 IOC 容器来管理,并且只能作⽤于 Spring 容器,使⽤纯 Java 代码实
    3. 在性能上,由于 Spring AOP 是基于 动态代理 来实现的,在容器启动时需要⽣成代理实
    例,在⽅法调⽤上也会增加栈的深度,使得 Spring AOP 的性能不如 AspectJ 的那么好。
    4. Spring AOP 致⼒于解决企业级开发中最普遍的 AOP( ⽅法织⼊ )
    AspectJ
    AspectJ 是⼀个易⽤的功能强⼤的 AOP 框架,属于 编译时增强 , 可以单独使⽤,也可以整合
    到其它框架中,是 AOP 编程的完全解决⽅案。 AspectJ 需要⽤到单独的编译器 ajc
    AspectJ 属于 静态织⼊ ,通过修改代码来实现,在实际运⾏之前就完成了织⼊,所以说它⽣成
    的类是没有额外运⾏时开销的,⼀般有如下⼏个织⼊的时机:
    1. 编译期织⼊( Compile-time weaving ):如类 A 使⽤ AspectJ 添加了⼀个属性,类 B 引⽤
    了它,这个场景就需要编译期的时候就进⾏织⼊,否则没法编译类 B
    2. 编译后织⼊( Post-compile weaving ):也就是已经⽣成了 .class ⽂件,或已经打成 jar
    了,这种情况我们需要增强处理的话,就要⽤到编译后织⼊。
    3. 类加载后织⼊( Load-time weaving ):指的是在加载类的时候进⾏织⼊,要实现这个时期
    的织⼊,有⼏种常见的⽅法

    事务
    Spring 事务的本质其实就是数据库对事务的⽀持,没有数据库的事务⽀持, Spring 是⽆法提
    供事务功能的。 Spring 只提供统⼀事务管理接⼜,具体实现都是由各数据库⾃⼰实现,数据
    库事务的提交和回滚是通过数据库⾃⼰的事务机制实现。
    23.Spring 事务的种类?
    Spring ⽀持 编程式事务 管理和 声明式 事务管理两种⽅式

     

    1. 编程式事务
    编程式事务管理使⽤ TransactionTemplate ,需要显式执⾏事务。
    2. 声明式事务
    3. 声明式事务管理建⽴在 AOP 之上的。其本质是通过 AOP 功能,对⽅法前后进⾏拦截,将
    事务处理的功能编织到拦截的⽅法中,也就是在⽬标⽅法开始之前启动⼀个事务,在执⾏
    完⽬标⽅法之后根据执⾏情况提交或者回滚事务
    4. 优点是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置⽂件中做相关的事务规
    则声明或通过 @Transactional 注解的⽅式,便可以将事务规则应⽤到业务逻辑中,减少业
    务代码的污染。唯⼀不⾜地⽅是,最细粒度只能作⽤到⽅法级别,⽆法做到像编程式事务
    那样可以作⽤到代码块级别。
    24.Spring 的事务隔离级别?
    Spring 的接⼜ TransactionDefinition 中定义了表⽰隔离级别的常量,当然其实主要还是对应数据
    库的事务隔离级别:
    1. ISOLATION_DEFAULT :使⽤后端数据库默认的隔离界别, MySQL 默认可重复读,
    Oracle 默认读已提交。
    2. ISOLATION_READ_UNCOMMITTED :读未提交
    3. ISOLATION_READ_COMMITTED :读已提交
    4. ISOLATION_REPEATABLE_READ :可重复读
    5. ISOLATION_SERIALIZABLE :串⾏化

     

    25.Spring 的事务传播机制?
    Spring 事务的传播机制说的是,当多个事务同时存在的时候 —— ⼀般指的是多个事务⽅法相
    互调⽤时, Spring 如何处理这些事务的⾏为。
    事务传播机制是使⽤简单的 ThreadLocal 实现的,所以,如果调⽤的⽅法是在新线程调⽤的,
    事务传播实际上是会失效的。

    Spring 默认的事务传播⾏为是 PROPAFATION_REQUIRED ,它适合绝⼤多数情况,如果多个
    ServiceX#methodX() 都⼯作在事务环境下(均被 Spring 事务增强),且程序中存在调⽤链
    Service1#method1()->Service2#method2()->Service3#method3() ,那么这 3 个服务类的三个⽅法通
    Spring 的事务传播机制都⼯作在同⼀个事务中。

    26. 声明式事务实现原理了解吗?
    就是通过 AOP/ 动态代理。
    Bean 初始化阶段创建代理对象 Spring 容器在初始化每个单例 bean 的时候,会遍历容器
    中的所有 BeanPostProcessor 实现类,并执⾏其 postProcessAfterInitialization ⽅法,在执⾏
    AbstractAutoProxyCreator 类的 postProcessAfterInitialization ⽅法时会遍历容器中所有的切
    ⾯,查找与当前实例化 bean 匹配的切⾯,这⾥会获取事务属性切⾯,查找 @Transactional
    注解及其属性值,然后根据得到的切⾯创建⼀个代理对象,默认是使⽤ JDK 动态代理创建
    代理,如果⽬标类是接⼜,则使⽤ JDK 动态代理,否则使⽤ Cglib
    在执⾏⽬标⽅法时进⾏事务增强操作 :当通过代理对象调⽤ Bean ⽅法的时候,会触发对
    应的 AOP 增强拦截器,声明式事务是⼀种环绕增强,对应接⼜
    MethodInterceptor ,事务增强对该接⼜的实现为 TransactionInterceptor ,类
    图如下:

     

    1 @Transactional 应⽤在⾮ public 修饰的⽅法上
    如果 Transactional 注解应⽤在⾮ public 修饰的⽅法上, Transactional 将会失效。
    是因为在 Spring AOP 代理时, TransactionInterceptor (事务拦截器)在⽬标⽅法执⾏前后进
    ⾏拦截, DynamicAdvisedInterceptor CglibAopProxy 的内部类)的 intercept ⽅法 或
    JdkDynamicAopProxy invoke ⽅法会间接调⽤ AbstractFallbackTransactionAttributeSource
    computeTransactionAttribute ⽅法,获取 Transactional 注解的事务配置信息。
    protected TransactionAttribute computeTransactionAttribute (Method method,
    Class targetClass) {
    // Don't allow no-public methods as required.
    if (allowPublicMethodsOnly() &&
    ! Modifier.isPublic(method.getModifiers())) {
    return null ;
    }
    此⽅法会检查⽬标⽅法的修饰符是否为 public ,不是 public 则不会获取 @Transactional 的属性
    配置信息。
    2 @Transactional 注解属性 propagation 设置错误
    TransactionDefinition.PROPAGATION_SUPPORTS :如果当前存在事务,则加⼊该事务;
    如果当前没有事务,则以⾮事务的⽅式继续运⾏。
    TransactionDefinition.PROPAGATION_NOT_SUPPORTED :以⾮事务⽅式运⾏,如果当前
    存在事务,则把当前事务挂起。
    TransactionDefinition.PROPAGATION_NEVER :以⾮事务⽅式运⾏,如果当前存在事务,
    则抛出异常。
    3 @Transactional 注解属性 rollbackFor 设置错误
    rollbackFor 可以指定能够触发事务回滚的异常类型。 Spring 默认抛出了未检查 unchecked 异常
    (继承⾃ RuntimeException 的异常)或者 Error 才回滚事务,其他异常不会触发回滚事务。

     

    // 希望⾃定义的异常可以进⾏回滚
    @Transactional (propagation = Propagation.REQUIRED,rollbackFor =
    MyException. class
    若在⽬标⽅法中抛出的异常是 rollbackFor 指定的异常的⼦类,事务同样会回滚。
    4 、同⼀个类中⽅法调⽤,导致 @Transactional 失效
    开发中避免不了会对同⼀个类⾥⾯的⽅法调⽤,⽐如有⼀个类 Test ,它的⼀个⽅法 A A 再调
    ⽤本类的⽅法 B (不论⽅法 B 是⽤ public 还是 private 修饰),但⽅法 A 没有声明注解事务,⽽ B
    ⽅法有。则外部调⽤⽅法 A 之后,⽅法 B 的事务是不会起作⽤的。这也是经常犯错误的⼀个地
    ⽅。
    那为啥会出现这种情况?其实这还是由于使⽤ Spring AOP 代理造成的,因为只有当事务⽅法
    被当前类以外的代码调⽤时,才会由 Spring ⽣成的代理对象来管理。
    //@Transactional
    @GetMapping ( "/test" )
    private Integer A () throws Exception {
    CityInfoDict cityInfoDict = new CityInfoDict();
    cityInfoDict.setCityName( "2" );
    /**
    * B 插⼊字段为 3 的数据
    */
    this .insertB();
    /**
    * A 插⼊字段为 2 的数据
    */
    int insert = cityInfoDictMapper.insert(cityInfoDict);
    return insert;
    }
    @Transactional ()
    public Integer insertB () throws Exception {
    CityInfoDict cityInfoDict = new CityInfoDict();
    cityInfoDict.setCityName( "3" );
    cityInfoDict.setParentCityId( 3 );
    return cityInfoDictMapper.insert(cityInfoDict);
    }
    这种情况是最常见的⼀种 @Transactional 注解失效场景
    @Transactional
    private Integer A () throws Exception {
    int insert = 0 ;
    try {
    CityInfoDict cityInfoDict = new CityInfoDict();
    cityInfoDict.setCityName( "2" );
    cityInfoDict.setParentCityId( 2 );
    /**
    * A 插⼊字段为 2 的数据
    */
    insert = cityInfoDictMapper.insert(cityInfoDict);
    /**
    * B 插⼊字段为 3 的数据
    */
    b.insertB();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    如果 B ⽅法内部抛了异常,⽽ A ⽅法此时 try catch B ⽅法的异常,那这个事务就不能正常回滚
    了,会抛出异常:
    org.springframework.transaction.UnexpectedRollbackException: Transaction
    rolled back because it has been marked as rollback - only

     

    28.Spring MVC 的核⼼组件?
    1. DispatcherServlet :前置控制器,是整个流程控制的 核⼼ ,控制其他组件的执⾏,进⾏
    统⼀调度,降低组件之间的耦合性,相当于总指挥。
    2. Handler :处理器,完成具体的业务逻辑,相当于 Servlet Action
    3. HandlerMapping DispatcherServlet 接收到请求之后,通过 HandlerMapping 将不同的请求
    映射到不同的 Handler
    4. HandlerInterceptor :处理器拦截器,是⼀个接⼜,如果需要完成⼀些拦截处理,可以实现
    该接⼜。
    5. HandlerExecutionChain :处理器执⾏链,包括两部分内容: Handler HandlerInterceptor
    (系统会有⼀个默认的 HandlerInterceptor ,如果需要额外设置拦截,可以添加拦截器)。
    6. HandlerAdapter :处理器适配器, Handler 执⾏业务⽅法之前,需要进⾏⼀系列的操作,
    包括表单数据的验证、数据类型的转换、将表单数据封装到 JavaBean 等,这些操作都是
    HandlerApater 来完成,开发者只需将注意⼒集中业务逻辑的处理上, DispatcherServlet
    通过 HandlerAdapter 执⾏不同的 Handler
    7. ModelAndView :装载了模型数据和视图信息,作为 Handler 的处理结果,返回给
    DispatcherServlet
    8. ViewResolver :视图解析器, DispatcheServlet 通过它将逻辑视图解析为物理视图,最终
    将渲染结果响应给客户端。
    29.Spring MVC 的⼯作流程?

    1. 客户端向服务端发送⼀次请求,这个请求会先到前端控制器 DispatcherServlet( 也叫中央控
    制器 )
    2. DispatcherServlet 接收到请求后会调⽤ HandlerMapping 处理器映射器。由此得知,该请求该
    由哪个 Controller 来处理(并未调⽤ Controller ,只是得知)
    3. DispatcherServlet 调⽤ HandlerAdapter 处理器适配器,告诉处理器适配器应该要去执⾏哪个
    Controller
    4. HandlerAdapter 处理器适配器去执⾏ Controller 并得到 ModelAndView( 数据和视图 ) ,并层层
    返回给 DispatcherServlet
    5. DispatcherServlet ModelAndView 交给 ViewReslover 视图解析器解析,然后返回真正的视
    6. DispatcherServlet 将模型数据填充到视图中
    7. DispatcherServlet 将结果响应给客户端
    Spring MVC 虽然整体流程复杂,但是实际开发中很简单,⼤部分的组件不需要开发⼈员创
    建和管理,只需要通过配置⽂件的⽅式完成配置即可,真正需要开发⼈员进⾏处理的只有
    Handler Controller View Model
    当然我们现在⼤部分的开发都是前后端分离, Restful 风格接⼜,后端只需要返回 Json 数据就⾏
    了。

     

    1. 客户端向服务端发送⼀次请求,这个请求会先到前端控制器 DispatcherServlet
    2. DispatcherServlet 接收到请求后会调⽤ HandlerMapping 处理器映射器。由此得知,该请求该
    由哪个 Controller 来处理
    3. DispatcherServlet 调⽤ HandlerAdapter 处理器适配器,告诉处理器适配器应该要去执⾏哪个
    Controller
    4. Controller 被封装成了 ServletInvocableHandlerMethod HandlerAdapter 处理器适配器去执⾏
    invokeAndHandle ⽅法,完成对 Controller 的请求处理
    5. HandlerAdapter 执⾏完对 Controller 的请求,会调⽤ HandlerMethodReturnValueHandler 去处
    理返回值,主要的过程:
    5.1. 调⽤ RequestResponseBodyMethodProcessor ,创建 ServletServerHttpResponse Spring
    原⽣ ServerHttpResponse 的封装)实例
    5.2. 使⽤ HttpMessageConverter write ⽅法,将返回值写⼊ ServletServerHttpResponse
    OutputStream 输出流中
    5.3. 在写⼊的过程中,会使⽤ JsonGenerator (默认使⽤ Jackson 框架)对返回值进⾏ Json
    列化
    6. 执⾏完请求后,返回的 ModealAndView null ServletServerHttpResponse ⾥也已经写⼊了
    响应,所以不⽤关⼼ View 的处理

    Spring Boot 约定⼤于配置 核⼼思想开展⼯作,相⽐ Spring 具有如下优势:
    1. Spring Boot 可以快速创建独⽴的 Spring 应⽤程序。
    2. Spring Boot 内嵌了如 Tomcat Jetty Undertow 这样的容器,也就是说可以直接跑起来,⽤
    不着再做部署⼯作了。
    3. Spring Boot ⽆需再像 Spring ⼀样使⽤⼀堆繁琐的 xml ⽂件配置。
    4. Spring Boot 可以⾃动配置 ( 核⼼ )Spring SpringBoot 将原有的 XML 配置改为 Java 配置,将
    bean 注⼊改为使⽤注解注⼊的⽅式 (@Autowire) ,并将多个 xml properties 配置浓缩在⼀个
    appliaction.yml 配置⽂件中。
    5. Spring Boot 提供了⼀些现有的功能,如量度⼯具,表单数据验证以及⼀些外部配置这样
    的⼀些第三⽅功能。
    6. Spring Boot 可以快速整合常⽤依赖(开发库,例如 spring-webmvc jackson-json
    validation-api tomcat 等),提供的 POM 可以简化 Maven 的配置。当我们引⼊核⼼依赖时,
    SpringBoot 会⾃引⼊其他依赖。

    32.SpringBoot ⾃动配置原理了解吗?
    SpringBoot 开启⾃动配置的注解是 @EnableAutoConfiguration ,启动类上的注解
    @SpringBootApplication 是⼀个复合注解,包含了 @EnableAutoConfiguration

    EnableAutoConfiguration 只是⼀个简单的注解,⾃动装配核⼼功能的实现实际是通
    AutoConfigurationImportSelector
    @AutoConfigurationPackage // main 同级的包下的所有组件注册到容器中
    @Import ({ AutoConfigurationImportSelector . class }) // 加载⾃动装配类
    xxxAutoconfiguration
    public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY =
    "spring.boot.enableautoconfiguration" ;
    Class [] exclude () default {};
    String [] excludeName () default {};
    }
    AutoConfigurationImportSelector 实现了 ImportSelector 接⼜,这个接⼜的作
    ⽤就是收集需要导⼊的配置类,配合 @Import( 就可以将相应的类导⼊到 Spring 容器中
    获取注⼊类的⽅法是 selectImports() ,它实际调⽤的是 getAutoConfigurationEntry
    这个⽅法是获取⾃动装配类的关键,主要流程可以分为这么⼏步:
    1. 获取注解的属性,⽤于后⾯的排除
    2. 获取所有需要⾃动装配的配置类的路径 :这⼀步是最关键的,从 META
    INF/spring.factories 获取⾃动配置类的路径
    3. 去掉重复的配置类和需要排除的重复类,把需要⾃动加载的配置类的路径存储起来
    protected AutoConfigurationImportSelector.AutoConfigurationEntry
    getAutoConfigurationEntry (AnnotationMetadata annotationMetadata) {
    if ( ! this .isEnabled(annotationMetadata)) {
    return EMPTY_ENTRY;
    } else {
    //1. 获取到注解的属性
    AnnotationAttributes attributes =
    this .getAttributes(annotationMetadata);
    //2. 获取需要⾃动装配的所有配置类,读取 META-INF/spring.factories ,获取
    ⾃动配置类路径
    List < String > configurations =
    this .getCandidateConfigurations(annotationMetadata, attributes);
    //3.1. 移除重复的配置
    configurations = this .removeDuplicates(configurations);
    //3.2. 处理需要排除的配置
    Set < String > exclusions =
    this .getExclusions(annotationMetadata, attributes);
    this .checkExcludedClasses(configurations, exclusions);
    configurations.removeAll(exclusions);
    configurations =
    this .getConfigurationClassFilter().filter(configurations);
    this .fireAutoConfigurationImportEvents(configurations,
    exclusions);
    return new
    AutoConfigurationImportSelector.AutoConfigurationEntry(configurations,
    exclusions);
    }
    }
     
    34.Springboot 启动原理?
    SpringApplication 这个类主要做了以下四件事情:
    1. 推断应⽤的类型是普通的项⽬还是 Web 项⽬
    2. 查找并加载所有可⽤初始化器 , 设置到 initializers 属性中
    3. 找出所有的应⽤程序监听器,设置到 listeners 属性中
    4. 推断并设置 main ⽅法的定义类,找到运⾏的主类

    什么是微服务?
    1. 2014 Martin Fowler 提出的⼀种新的架构形式。微服务架构是⼀种 架构模式 ,提倡将
    单⼀应⽤程序划分成⼀组⼩的服务,服务之间相互协调,互相配合,为⽤户提供最终价
    值。每个服务运⾏在其独⽴的进程中,服务与服务之间采⽤轻量级的通信机制 ( HTTP
    Dubbo) 互相协作,每个服务都围绕着具体的业务进⾏构建,并且能够被独⽴的部署到⽣产
    环境中,另外,应尽量避免统⼀的,集中式的服务管理机制,对具体的⼀个服务⽽⾔,应
    根据业务上下⽂,选择合适的语⾔、⼯具 ( Maven) 对其进⾏构建。
    2. 微服务化的核⼼就是将传统的⼀站式应⽤,根据业务拆分成⼀个⼀个的服务,彻底地去耦
    合,每⼀个微服务提供单个业务功能的服务,⼀个服务做⼀件事情,从技术⾓度看就是⼀
    种⼩⽽独⽴的处理过程,类似进程的概念,能够⾃⾏单独启动或销毁,拥有⾃⼰独⽴的数
    据库。

    微服务架构主要要解决哪些问题?
    1. 服务很多,客户端怎么访问,如何提供对外⽹关 ?
    2. 这么多服务,服务之间如何通信 ? HTTP 还是 RPC?
    3. 这么多服务,如何治理 ? 服务的注册和发现。
    4. 服务挂了怎么办?熔断机制。

    有哪些主流微服务框架?
    1. Spring Cloud Netflix
    2. Spring Cloud Alibaba
    3. SpringBoot + Dubbo + ZooKeeper

     

  • 相关阅读:
    是顺流还是逆流?未来物流作业是否将被机器人全面取代?
    java解析c结构体的数据
    _linux 进程间通信(匿名管道)
    el-table 设置固定宽度弹框
    应用在温度测量仪领域中的数字温度传感芯片
    xxl-job架构原理讲解
    Python的无限魅力:探索其广泛应用领域
    Magisk Delta以及EdXposed工具在逍遥模拟器上安装教程
    使用前端JS函数进行处理 四舍五入保留后两位小数
    LabVIEW性能和内存管理 1
  • 原文地址:https://blog.csdn.net/chenyong6301567/article/details/126741390