返回

揭开SpringBoot注解@RefreshScope的神秘面纱

后端

使用 @RefreshScope 动态刷新 Spring Bean 属性

你是否遇到过这样的问题:

  • 修改了 Bean 的属性,却发现项目并没有重新启动,也无法拿到最新的值?

别着急,这不是你的错! 这是一个常见的痛点,尤其是在微服务配置中心的场景下。为了解决这个问题,SpringBoot 中提供了 @RefreshScope 这个注解,它可以用来刷新 Bean 中的属性配置,让我们修改了 Bean 属性后,项目无需重新启动,即可拿到最新的值。

@RefreshScope 注解原理

@RefreshScope 注解位于 org.springframework.cloud.context.scope.refresh 包中,它是一个作用于类级别的注解,主要用来定义一个 Bean 的刷新范围。

源码解析:

@Target({ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@ConditionalOnBean(RefreshScopeRefresher.class)
public @interface RefreshScope {
    ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}

重要属性:

  • proxyMode:指定了 Bean 的代理模式,默认值为 TARGET_CLASS,表示使用 CGLIB 动态代理技术来创建 Bean 的代理对象。

工作机制:

当我们在一个 Bean 上使用了 @RefreshScope 注解后,SpringBoot 会自动创建一个该 Bean 的代理对象,并将其注入到 Spring 上下文中。当 Bean 的属性发生变化时,SpringBoot 会自动调用代理对象的 refresh() 方法,从而刷新 Bean 的属性值。

示例代码:

@RefreshScope
public class MyBean {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在上面的代码中,我们使用 @RefreshScope 注解标注了 MyBean 类,这就意味着我们可以通过修改 name 属性来刷新 Bean 的属性值。

使用方法:

@Autowired
private MyBean myBean;

public void updateName(String newName) {
    myBean.setName(newName);
}

在上面的代码中,我们通过调用 updateName() 方法来修改 myBeanname 属性,当我们修改了 name 属性后,SpringBoot 会自动调用 myBean 代理对象的 refresh() 方法,从而刷新 Bean 的属性值。

优点:

  • 可以动态刷新 Bean 的属性值,而无需重新启动项目。
  • 使用简单,只需要在 Bean 上添加 @RefreshScope 注解即可。
  • 支持多种代理模式,可以根据需要选择合适的代理模式。

如果你正在使用 SpringBoot,并且希望能够动态刷新 Bean 的属性值,那么 @RefreshScope 注解是一个非常有用的工具。

常见问题解答:

  1. 什么时候可以使用 @RefreshScope 注解?

    • 当你希望在修改 Bean 的属性后,无需重新启动项目就能拿到最新的值时。
  2. 如何使用 @RefreshScope 注解?

    • 在希望刷新的 Bean 类上添加 @RefreshScope 注解即可。
  3. @RefreshScope 注解支持哪些代理模式?

    • TARGET_CLASS:使用 CGLIB 动态代理。
    • INTERFACES:使用 JDK 动态代理。
  4. 修改了 Bean 的属性后,如何刷新 Bean 的属性值?

    • SpringBoot 会自动调用代理对象的 refresh() 方法来刷新 Bean 的属性值。
  5. @RefreshScope 注解有什么优点?

    • 动态刷新 Bean 的属性值,无需重新启动项目。
    • 使用简单,易于使用。
    • 支持多种代理模式,灵活性强。