SpringCloud 配置动态刷新 @RefreshScope 注解

本文详细探讨了SpringCloud中@RefreshScope动态刷新的原理,包括@Scope和@RefreshScope注解的作用,以及如何实现配置的动态刷新。同时,文章提到了@RefreshScope使用时的注意事项,如不能用于final类,以及可能导致的动态刷新失效问题。此外,还介绍了不使用@RefreshScope也能实现动态刷新的方法,以及使用@RefreshScope的bean可能遇到的问题,最后讨论了其他配置刷新方式。
摘要由CSDN通过智能技术生成

一、@RefreshScope动态刷新原理

在SpringIOC中,BeanScope(Bean的作用域)影响了Bean的管理方式。

Bean的作用域:

例如创建Scope=singleton的Bean时,IOC会保存实例在一个Map中,保证这个Bean在一个IOC上下文有且仅有一个实例。

SpringCloud新增了一个自定义的作用域:refresh(可以理解为“动态刷新”),同样用了一种独特的方式改变了Bean的管理方式,使得其可以通过外部化配置(.properties)的刷新,在应用不需要重启的情况下热加载新的外部化配置的值。

这个scope是如何做到热加载的呢?RefreshScope主要做了以下动作:

单独管理Bean生命周期

创建Bean的时候如果是RefreshScope就缓存在一个专门管理的ScopeMap中,这样就可以管理Scope是Refresh的Bean的生命周期了(所以含RefreshScope的其实一共创建了两个bean)。

重新创建Bean

外部化配置刷新之后,会触发一个动作,这个动作将上面的ScopeMap中的Bean清空,这样这些Bean就会重新被IOC容器创建一次,使用最新的外部化配置的值注入类中,达到热加载新值的效果。

spring cloud configsprring cloud alibaba nacos作为配置中心,其实现原理就是通过@RefreshScope 来实现对象属性的的动态更新。

@RefreshScope 实现配置的动态刷新需要满足一下几点条件:

  • @Scope注解

  • @RefreshScope注解

  • RefreshScope类

  • GenericScope类

  • Scope接口

  • ContextRefresher类

@RefreshScope 能实现动态刷新全仰仗着@Scope 这个注解。

1. @Scope注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {

 /**
  * Alias for {@link #scopeName}.
  * @see #scopeName
  */
 @AliasFor("scopeName")
 String value() default "";

 /**
  *  singleton  表示该bean是单例的。(默认)
     *  prototype    表示该bean是多例的,即每次使用该bean时都会新建一个对象。
     *  request        在一次http请求中,一个bean对应一个实例。
     *  session        在一个httpSession中,一个bean对应一个实例
  */
 @AliasFor("value")
 String scopeName() default "";

 /**
    *   DEFAULT   不使用代理。(默认)
 *  NO    不使用代理,等价于DEFAULT。
 *  INTERFACES  使用基于接口的代理(jdk dynamic proxy)。
 *  TARGET_CLASS 使用基于类的代理(cglib)。
    */
 ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;

}

@Scope有两个主要属性value 和 proxyMode,其中proxyMode就是@RefreshScope 实现的本质了。

proxyMode属性是一个ScopedProxyMode类型的枚举对象。

public enum ScopedProxyMode {
    DEFAULT,
    NO,
    INTERFACES,// JDK 动态代理
    TARGET_CLASS;// CGLIB 动态代理

    private ScopedProxyMode() {
    }
}

proxyMode属性的值为ScopedProxyMode.TARGET_CLASS时,会给当前创建的bean 生成一个代理对象,会通过代理对象来访问,每次访问都会创建一个新的对象。

2. @RefreshScope注解

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope("refresh")
@Documented
public @interface RefreshScope {
 /**
  * @see Scope#proxyMode()
  */
 ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

它使用就是 @Scope ,一个scopeName="refresh"@Scope

proxyMode值为ScopedProxyMode.TARGET_CLASS,通过CGLIB动态代理的方式生成Bean。

使用 @RefreshScope 注解的 bean,不仅会生成一个beanName的bean,默认情况下同时会生成 scopedTarget.beanName的 bean。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值