Spring

月伴飞鱼 2024-10-12 12:52:33
Java框架
支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者!

Bean作用域

image-20240114182133223

默认作用域是Singleton,多个线程访问同一个Bean时会存在线程不安全问题。

保障线程安全方法:

  • Bean对象中尽量避免定义可变的成员变量。
  • 在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal中。

启动初始化方式

@PostConstruct

Bean创建期间由 Spring 调用的初始化方法。

使用:将 @PostConstruct 注解添加到方法上就行。

InitializingBean

可以实现 InitializingBean 接口,让 Spring 调用某个初始化方法。

Controller和Service是线程安全的吗

默认情况下,Scope值是单例(Singleton)的,是线程不安全的。

尽量不要在@Controller/@Service等容器中定义静态变量:

  • 不论是单例(Singleton)还是多实例(Prototype)都是线程不安全的。

BeanFactoryPostProcessor 和 BeanPostProcessor

BeanFactoryPostProcessor

  • Bean 工厂实例化 Bean 之前对 Bean 的定义进行修改。

  • 可以读取和修改 Bean 的定义元数据,例如修改 Bean 的属性值、添加额外的配置信息等。

BeanPostProcessor

  • Bean 实例化后对 Bean 进行增强或修改。
  • 它可以在 Bean 的初始化过程中对 Bean 进行后处理,例如对 Bean 进行代理、添加额外的功能等。

启动流程

SpringBoot 的启动流程主要有以下几个核心步骤:

序号 步骤 说明
1 创建启动容器 创建 DefaultBootstrapContext,用于引导 IOC 容器启动。
2 启动监听器 监听应用启动时发生的相关事件。
3 准备应用环境 配置应用所需的环境。
4 创建应用上下文 创建核心 IOC 容器。
5 准备应用上下文 加载 BeanDefinition
6 刷新应用上下文 创建 Bean
7 调用 Runner 执行用户自定义的 ApplicationRunner / CommandLineRunner,用于扩展。

Bean生产过程

Bean 的生产大致有 4 个核心步骤:

  • BeanDefinitionLoader 加载 XML 文件或注解中定义的内容。

  • BeanDefinitionLoader 将加载的内容转换成 BeanDefinition

  • BeanDefinitionRegistryBeanDefinition 注册到 BeanFactory 中。

  • BeanFactory 负责将 BeanDefinition 生成 Bean

Bean的生命周期

Spring的生命周期大致分为:创建 -> 属性填充 -> 初始化Bean -> 使用 -> 销毁 几个核心阶段。

创建阶段:

  • 主要是创建对象,对象的创建权交由Spring管理。

属性填充阶段:

  • 主要是进行依赖的注入,将当前对象依赖的Bean对象,从Spring容器中找出来,然后填充到对应的属性中去。

初始化Bean阶段:

  • 包括回调各种Aware接口、回调各种初始化方法、生成AOP代理对象也在该阶段进行,该阶段主要是完成初始化回调。

使用Bean阶段:

  • 主要是Bean创建完成,在程序运行期间,提供服务的阶段。

销毁Bean阶段:

  • 主要是容器关闭或停止服务,对Bean进行销毁处理。
image-20240114181239744

循环依赖

循环依赖指的是一个实例或多个实例存在相互依赖的关系(类之间循环嵌套引用)。

public class AService {
    private BService bService;
}

public class BService {
    private AService aService;
}

Bean的创建步骤:

在创建 Bean 之前,Spring 会通过扫描获取 BeanDefinition

BeanDefinition就绪后会读取 BeanDefinition 中所对应的 Class 来加载类。

实例化阶段:根据构造函数来完成实例化 (未属性注入以及初始化的对象(原始对象))。

属性注入阶段:对 Bean 的属性进行依赖注入。

如果 Bean 的某个方法有AOP操作,则需要根据原始对象生成代理对象

  • AOP代理是BeanPostProcessor实现的,而BeanPostProcessor是发生在属性注入阶段后的。

最后把代理对象放入单例池(一级缓存singletonObjects)中。

为什么 Spring Bean 会产生循环依赖问题?

AService 创建时,会先对 AService 实例化生成一个原始对象。

然后在进行属性注入时发现了需要 BService 对应的 Bean

此时就会去为 BService 进行创建,在 BService 实例化后生成一个原始对象后进行属性注入。

此时会发现也需要 AService 对应的 Bean

image-20231014162629222

三大循环依赖问题场景:

单例作用域下的Setter方法注入/Field属性注入出现的循环依赖。

  • Spring 中是不会产生循环依赖问题的,这主要是靠 三级缓存 机制解决。

单例作用域下的构造器注入出现的循环依赖。

  • 因为 构造器注入 发生在 实例化阶段,而 Spring 解决循环依赖问题依靠的 三级缓存属性注入阶段
  • 也就是说调用构造函数时还未能放入三级缓存中,所以无法解决 构造器注入 的循环依赖问题。

原型作用域下的属性注入出现的循环依赖问题。

  • 因为 Spring 不会缓存 原型 作用域的 Bean,所以 Spring 无法解决 原型 作用域的 Bean。

三级缓存:

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

一级缓存(singletonObjects):缓存的是已经实例化、属性注入、初始化后Bean 对象。

二级缓存(earlySingletonObjects):缓存的是实例化后,但未属性注入、初始化Bean对象(用于提前暴露 Bean)。

三级缓存(singletonFactories):

  • 缓存的是一个 ObjectFactory
  • 主要作用是生成原始对象进行 AOP 操作后的代理对象(这一级缓存主要用于解决 AOP 问题)。

为什么缓存可以解决循环依赖问题?

在创建 AService 时,实例化后将 原始对象 存放到缓存中(提早暴露)。

然后依赖注入时发现需要 BService,便会去创建 BService

实例化后同样将 原始对象 存放到缓存中,然后依赖注入时发现需要 AService 便会从缓存中取出并注入。

这样 BService 就完成了创建,随后 AService 也就能完成属性注入,最后也完成创建。

image-20231014163323751

为什么还需要第三级缓存?

第三级缓存(singletonFactories 是为了处理 SpringAOP的。

如果 AService 中方法没有使用 AOP 操作。

会发现 BService 注入的 原始对象 与最后 AService 完成创建后的最终对象是同一个对象

如果 AService 方法中有 AOP 操作时,当 AService 的原始对象赋值(注入)给 BService

AService 会进行 AOP 操作产生一个 代理对象,这个代理对象最后会被放入单例池(一级缓存)中。

也就是说此时 BService 中注入的对象是原始对象,而 AService 最终创建的完成后是代理对象。

这样就会导致 BService 依赖的 AService 和 最终的 AService 不是同一个对象

出现这个问题原因:

AOP 是通过 BeanPostProcessor 实现的,而 BeanPostProcessor 是在 属性注入阶段后 才执行的。

所以会导致注入的对象有可能和最终的对象不一致

image-20231014163541994

Spring 是如何通过第三级缓存来避免 AOP 问题的?

三级缓存通过利用 ObjectFactorygetEarlyBeanReference() 做到了提前执行 AOP 操作从而生成代理对象。

在上移到二级缓存时,可以做到如果 Bean 中有 AOP 操作。

那么提前暴露的对象会是 AOP 操作后返回的代理对象;如果没有 AOP 操作,那么提前暴露的对象会是原始对象。

  • 只有等完成了属性注入、初始化后的 Bean 才会上移到一级缓存(单例池)中。

这样就能做到出现循环依赖问题时,注入依赖的对象和最终生成的对象是同一个对象。

  • 相当于 AOP 提前在属性注入前完成,这样就不会导致后面生成的代理对象与属性注入时的对象的不一致。

设计模式

单例设计模式 :

  • Spring 中的 Bean 默认都是单例的。

⼯⼚设计模式 :

  • 通过 BeanFactory、 ApplicationContext 创建 Bean 对象。

代理设计模式 :

  • Spring AOP 功能的实现。

观察者模式:

  • Spring 事件驱动模型。

适配器模式:

  • Spring AOP 的增强或通知(Advice)使⽤到了适配器模式、Spring MVC 中也是⽤到了适配器模式适配 Controller

基本概念

IOC(控制反转)

Spring中有一个容器,我们将Bean放到这个容器中,让这个容器为我们创建实例,当需要时我们直接从这个容器中进行获取即可。

使用IOC最大的好处就是减少了代码的耦合度,降低了程序的维护成本。

img

实现原理:

Spring实现IOC容器的是通过:工厂 + 反射,实现的。

如果是基于全注解形式的话,只是将读取配置文件的步骤改成了读取配置类。

然后通过配置类获取需要创建实现的Bean,并通过反射将其创建。

img

DI依赖注入

站在容器的角度,将对象创建依赖的其他对象注入到对象中。

AOP

AOP 面向切面的编程:在不改变源代码的情况下,实现对逻辑功能的修改。

  • 常用的场景包括记录日志、异常处理、性能监控、安全控制(例如拦截器)等。

AOP 原理:

动态的生成代理类,代理类的执行过程为:

  • 执行增加的代码(例如方法日志记录)-> 回调原方法 -> 增加的代码逻辑。

Spring AOP 动态代理采用 JDK 动态代理或 CGlib 动态生成代理类。

  • 判断被切面的类是否有其实现的接口。
  • 如果有对应的接口,则采用 JDK 动态代理,否则采用 CGlib 字节码生成机制动态代理方式。
@SuppressWarnings("serial")
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface()) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

SpringMVC

SpringMVC是一个基于Servlet容器的Web应用框架。

  • Servlet容器通常指Tomcat等服务容器。

Servlet容器会负责监听端口消息并映射为Request/Response对象,然后交给Servlet实例去处理。

SpringMVC框架的作用核心就是Servlet实例。

  • 这个实例在Spring中默认是DispatcherServlet。

Spring MVC结构图

客户端(浏览器)发送请求,直接请求到 DispatcherServlet。

DispatcherServlet 根据请求信息调⽤ HandlerMapping,解析请求对应的 Handler。

解析到对应的 Handler (也就是 Controller 控制器)后,开始由HandlerAdapter 适配器处理。

HandlerAdapter 会根据 Handler 来调⽤真正的处理器开处理请求,并处理相应的业务逻辑。

处理器处理完业务后,会返回⼀个 ModelAndView 对象, Model 是返回的数据对象。

ViewResolver 会根据逻辑 View 查找实际的 View。

DispaterServlet 把返回的 Model 传给 View(视图渲染)。

把 View 返回给请求者(浏览器)。

核心组件DispatcherServlet

在Spring容器启动阶段读取映射规则,如RequestMapping。

在请求到来的时候,按照加载的请求映射规则找到合适的处理方法。

当处理请求的过程中出现了异常,对异常进行处理,如返回合适的界面或状态码。

解析返回View的主题、时区等信息。

渲染返回的视图。

DispatcherServlet功能图

请求映射HandlerMapping

请求映射用于根据请求找到该请求需要调用的所有方法,包含过滤器和处理方法等。

比较常用的一种请求映射是RequestMappingHandlerMapping。

  • 从名称上可以看出来这个HandlerMapping是用于处理@RequestMapping注解请求映射的类。

该类的主要作用是在收到请求之后,按顺序拿到所有需要调用的方法(主要包含拦截器和处理方法),然后一一调用这些方法。

Handler Mapping原理

拦截器HandlerInterceptor

Spring的拦截器可以灵活的在请求处理前、请求处理后和请求完成三个阶段自定义操作,比如用户权限校验等。

Hadler Interceptor

处理方法Handler

处理方法在DispatcherServlet定义为Object类型,如果使用了@RequestMapping来根据请求查找处理方法,那么查找到的处理方法就是HandlerMethod类型,对应于Controller中添加了对应RequestMapping的方法。

处理方法适配器HandlerAdapter

DispatcherServlet从HandlerMapping中获取到的处理方法是Object类型,意味着不同的处理方法可能返回不同的对象。

DispatcherServlet本身是一个调度器,不应该关注如何调用不同的处理方法。

  • 所以Spring提供了HandlerAdapter列表用户处理不同的调度方法。

Hadler

异常处理HandlerExceptionResolver

HandlerExceptionResolver用于处理请求过程中出现的异常。

  • 日常开发中使用比较多的是ExceptionHandlerExceptionResolver,也就是@ExceptionHandler注解。

@ExceptionHander可以放在@ControllerAdvice注解的类中,表示对所有的Controller都会生效。

事务

嵌套事务

举例,methodA 中调用了 methodB,两个方法都有对数据库的操作,而且都需要事务。

这种多个方法调用链中都有事务的场景,就是嵌套事务。

要注意的是,并不是说多个方法使用一个事务才叫嵌套,哪怕是不同的事务,只要在这个方法的调用链中,都是嵌套事务。

// MethodA:
public void methodA(){
    int updated = connection.prepareStatement().executeUpdate();
    methodB();
    // ...
}

// MethodB:
public void methodB(){
    // ...
}

事务传播行为

方法调用链中的子方法,是用一个新事务,还是使用当前事务呢?

  • 这个子方法决定使用新事务还是当前事务(或不使用事务)的策略,就叫事务传播。
Spring传播行为 介绍
REQUIRED 支持当前事务,如果不存在,就新建一个
SUPPORTS 支持当前事务,如果不存在,就不使用事务
MANDATORY 支持当前事务,如果不存在,抛出异常
REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
NEVER 以非事务方式运行,如果有事务存在,抛出异常
NESTED 如果当前事务存在,则嵌套事务执行(嵌套式事务)

事务失效

1、事务方法被Final、Static关键字修饰:

如果一个方法被声明为final或者static,则该方法不能被子类重写

  • 也就是说无法在该方法上进行动态代理,这会导致Spring无法生成事务代理对象来管理事务。
@Service
public class ServiceImpl  {

    @Autowired
    private TestMapper1 mapper1;
    
    @Autowired
    private TestMapper2 mapper2;

    @Transactional
    public final void add(Test test) {
        mapper1.save();
        mapper2.save();
    }
}

2、同一个类中,方法内部调用:

事务是通过Spring AOP代理来实现的,而在同一个类中,一个方法调用另一个方法时

  • 调用方法直接调用目标方法的代码,而不是通过代理类进行调用
    • 即调用目标add方法不是通过代理类进行的,因此事务不生效。

解决方案:可以新建多一个类,让这两个方法分开,分别在不同的类中。

@Service
public class ServiceImpl implements Service {

    @Autowired
    private TestMapper1 mapper1;
    
    @Autowired
    private TestMapper2 mapper2;
    
    public void add(Test test){
     // 调用内部的事务方法
     this.add(test);
   }

    @Transactional
    public void add(Test test) {
        mapper1.save();
        mapper2.save();
    }
}

3、方法的访问权限不是Public:

代理的事务方法不是public的话,springcomputeTransactionAttribute()就会返回null

  • 这时事务属性不存在了。

4、RollbackFor属性配置错误:

rollbackFor属性指定的异常必须是Throwable或者其子类。

  • 默认情况下,RuntimeExceptionError两种异常都是会自动回滚的。

代码例子:

  • 指定了rollbackFor = Error.class,但是抛出的异常又是Exception,因此事务就不生效。
    @Transactional(rollbackFor = Error.class)
    public void add(Test test) {
        mapper1.save(test);
        mapper2.save(test);
        //模拟异常抛出
        throw new Exception();
    }

5、事务注解被覆盖导致事务失效:

MyTestServiceMyService的子类,并且覆盖了doSomething()方法。

  • 在该方法中,使用了不同的传播行为(REQUIRES_NEW)来覆盖父类的@Transactional注解。

在这种情况下,当调用MyTestServicedoSomething()方法时

  • 由于子类方法中的注解覆盖了父类的注解,Spring框架将不会在父类的方法中启动事务。

因此,当MyRepositorysave()方法被调用时,事务将不会被启动,也不会回滚。

  • 这将导致数据不一致的问题,因为在MyRepositorysave()方法中进行的数据库操作将不会回滚。
public interface MyRepository {
    @Transactional
    void save(String data);
}

public class MyRepositoryImpl implements MyRepository {
    @Override
    public void save(String data) {
        // 数据库操作
    }
}

public class MyService {

    @Autowired
    private MyRepository myRepository;

    @Transactional
    public void doSomething(String data) {
        myRepository.save(data);
    }
}

public class MyTestService extends MyService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void doSomething(String data) {
        super.doSomething(data);
    }
}

6、嵌套事务:

如果saveFlow出现运行时异常,会继续往上抛,到外层add的方法

  • 导致mapper.save也会回滚啦。

如果不想因为被内部嵌套的事务影响,可以用try-catch包住。

@Service
public class ServiceInOutService {

    @Autowired
    private FlowService flowService;
    @Autowired
    private Mapper mapper;

    @Transactional
    public void add(Test test) throws Exception {
        mapper.save(test);
        flowService.saveFlow(test);
    }
}

@Service
public class FlowService {

    @Autowired
    private Mapper mapper;

    @Transactional(propagation = Propagation.NESTED)
    public void saveFlow(Test test) {
        mapper.save(test);
        throw new RuntimeException();
    }
}
@Transactional
public void add(Test test) throws Exception {
  mapper.save(test);
  try {
    flowService.saveFlow(test);
  } catch (Exception e) {
    log.error("save flow fail,message:{}",e.getMessage());
  }
}

7、事务多线程调用:

Spring事务是基于线程绑定的,每个线程都有自己的事务上下文

  • 而多线程环境下可能会存在多个线程共享同一个事务上下文的情况,导致事务失效。

Spring事务管理器通过使用线程本地变量(ThreadLocal)来实现线程安全。

@Service
public class Service {

    @Autowired
    private Mapper1 mapper1;

    @Mapper1
    private FlowService flowService;

    @Transactional
    public void add(Test test) {
        mapper1.save(test);
        //多线程调用
        new Thread(() -> {
            flowService.save(test);
        }).start();
    }
}

@Service
public class FlowService {

    @Autowired
    private Mapper1 mapper1;

    @Transactional
    public void save(Test test) {
        mapper1.saveFlow(test);
    }
}

8、异常被捕获并处理了,没有重新抛出:

事务中的异常已经被业务代码捕获并处理

  • 而没有被正确地传播回事务管理器,事务将无法回滚。

spring事务方法中,当我们使用了try-catchcatch住异常,一定要重新把异常抛出来。

@Service
public class ServiceImpl implements Service {

    @Autowired
    private Mapper1 mapper1;

    @Autowired
    private Mapper2 mapper2;

    @Transactional
    public void add(Test test) {
        try {
            mapper1.save();
            mapper2.save();
        } catch (Exception e) {
            log.error("add error,id:{},message:{}", tianluo.getId(),e.getMessage());
            //throw e;
        }
    }

}

9、手动抛了别的异常:

如果手动抛了Exception异常,但是是不会回滚的

  • 因为Spring默认只处理RuntimeException和Error,对于普通的Exception不会回滚
    • 除非,用rollbackFor属性指定配置。

@Transactional加不加rollbackFor=Exception.class的区别

@Transactional只能回滚RuntimeExceptionRuntimeException下面的子类抛出的异常,不能回滚Exception异常。

如果需要支持回滚Exception异常请用@Transactional(rollbackFor = Exception.class)

这里如果是增删改的时候我建议都使用@Transactional(rollbackFor = Exception.class)

SpringBoot

Spring Boot Starter

实现一个Starter:

  • Starter 命名。
  • 自动配置类,用来初始化相关的 bean。
  • 指明自动配置类的配置文件 spring.factories
  • 自定义属性实体类,声明 starter 的应用配置属性。

名字:

官方的 starter 的命名格式为 spring-boot-starter-{name}

非官方的 starter 的命名格式为 {name}-spring-boot-starter,把自定义的 starter 命名为 fish-spring-boot-starter,命名在 pom 文件里。

<groupId>fish.springcloud</groupId>
<artifactId>fish-spring-boot-starter</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

引入自动配置包及其它相关依赖包:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

创建 spring.factories 文件:

resource/META-INF 目录下创建名称为 spring.factories 的文件。

当 Spring Boot 启动的时候,会在 classpath 下寻找所有名称为 spring.factories 的文件,然后运行里面的配置指定的自动加载类,将指定类(一个或多个)中的相关 bean 初始化。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  kite.springcloud.boot.starter.example.FishAutoConfigure

编写自动配置类:

自动配置类是用来初始化 starter 中的相关 bean 的。

@Configuration
@ConditionalOnClass(FishService.class)
@EnableConfigurationProperties(FishProperties.class)
@Slf4j
public class FishAutoConfigure {

    @Autowired
    private FishProperties fishProperties;

    @Bean
    @ConditionalOnMissingBean(FishService.class)
    @ConditionalOnProperty(prefix = "fish.example",value = "enabled", havingValue = "true")
    FishService fishService(){
        return new FishService(fishProperties);
    }
}

实现属性配置类:

@Data
@ConfigurationProperties("fish.example")
public class FishProperties {

    private String host;

    private int port;
}

实现相关功能类:

@Slf4j
public class FishService {

    private String host;

    private int port;

    public FishService(FishProperties fishProperties){
        this.host = fishProperties.getHost();
        this.port = fishProperties.getPort();
    }

    public void print(){
        log.info(this.host + ":" +this.port);
    }
}

打包:

通过 maven mvn install命令将 starter 安装到本地 maven 仓库。

也可以通过 mvn package deploy 发布到私服。或者发布到中央仓库。

自动配置原理

Spring启用全自动配置功能的注解就是@EnableAutoConfiguration,应用添加了@EnableAutoConfiguration注解之后,会读取所有jar包下面的spring.factories文件,获取文件中配置的自动装配模块,然后去装配对应的模块。

@EnableAutoConfiguration的功能可总结为:

  • 使Spring启用factories机制导入各个starter模块的配置。

启动流程

构造SpringBootApplication对象和执行run方法

核心注解@SpringBootConfiguration标识启动类为配置类。

@EnableAutoConfiguration通过内部@Import注解AutoConfigurationImportSelector.class实现自动装配。

@ComponentScan默认扫描当前目录及子目录下的Bean。

SpringBootApplication的构造方法主要做了几件事:

  • 根据是否加载servlet类判断是否是web环境。
  • 获取所有初始化器,扫描所有META-INF/spring.factories下的ApplicationContextInitializer子类通过反射拿到实例,在spring实例启动前后做一些回调工作。
  • 获取所有监听器,同2,也是扫描配置加载对应的类实例。

run方法主要创建了配置环境、事件监听、启动应用上下文,其中refresh方法贯穿springbean的生命周期。

执行bean的生命周期的前后置钩子方法,并且处理spring的注解标注的类。

onRefresh中通过Java代码构建出tomcat容器并启动。

img

SpringCloud

Spring Cloud 就是分布式微服务架构的⼀站式解决方案,是微服务架构落地的多种技术的集合。

具体包含:

  • 服务注册与发现、配置中心、服务网关、智能路由、负载均衡、断路器、监控跟踪、分布式消息队列等等。

Spring Cloud 包含很多子项目:比如:NetflixAlibaba

SpringCloud中文网:https://springcloud.cc

官网:https://spring.io/projects/spring-cloud/

发布计划

版本号 版本 说明
BUILD-XXX 开发版 开发团队内部使用
M 里程碑版 MileStone,M1 表示第 1 个里程碑版本,一般同时标注 PRE,表示预览版
RC 候选发布版 Release Candidate,正式发布版的前一个观察期,不添加新功能,主要着重于除错
SR 正式发布版 Service Release,SR1 表示第 1 个正式版本,一般同时标注 GA,表示稳定版本
GA 稳定版 经过全面测试并可对外发行称之为GA(General Availability

希腊字母版本

Base:

  • 设计阶段。只有相应的设计没有具体的功能实现。

Alpha:

  • 软件的初级版本,存在较多的 Bug

Beta:

  • 表示相对 Alpha 有了很大的进步,消除了严重的 Bug,还存在一些潜在的 Bug。

Gamma:

  • Beta 版做过一些修改,成为正式发布的候选版本(Release Candidate)。

Release:

  • 该版本表示最终版。
Spring Cloud 第一代 Spring Cloud 第二代
网关 Spring Cloud Zuul Spring Cloud Gateway
注册中心 Eureka,Consul,ZooKeeper 阿里 Nacos,拍拍贷 Radar 等
配置中心 Spring Cloud Config 阿里 Nacos,携程 Apollo,随行付 Config Keeper 等
客户端负载均衡 Ribbon spring-cloud-commons 的 Spring Cloud LoadBalancer
熔断器 Hystrix spring-cloud-r4j(Resilience4J),阿里 Sentinel 等
链路追踪 Sleuth + Zipkin Apache Skywaling,OpenTracing 等

EurekaHystrix 等不再继续开发或维护,但是目前来说不影响使用。

Dubbo和SpringCloud对比

Spring Cloud 抛弃了 DubboRPC通信。

  • 采用的是基于HTTPREST方式。

二者解决的问题域不一样:

  • Dubbo的定位是一款RPC框架,而SpringCloud的目标是微服务架构下的一站式解决方案。

Spring Cloud Netflix

Netflix Eureka

  • 一个基于 Rest 服务的服务治理组件。

Netflix Ribbon

  • 客户端负载均衡的服务调用组件。

Netflix Hystrix

  • 容错管理工具,实现断路器模式。

Netflix Feign

  • 基于 RibbonHystrix 的声明式服务调用组件。

Netflix Zuul

  • 微服务网关,提供动态路由,访问过滤等服务。

Netflix Archaius

  • 配置管理 API

Spring Cloud Alibaba

Nacos

  • 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

Sentinel

  • 面向分布式服务架构的轻量级流量控制产品。

RocketMQ

  • 一款开源的分布式消息系统。

Dubbo

  • 一款高性能 Java RPC 框架,用于实现服务通信。

Seata

  • 一个易于使用的高性能微服务分布式事务解决方案。
支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者!