spring @DependsOn 实现@Value动态刷新

本文探讨了Spring框架中@DependsOn注解的作用,用于控制Bean的加载顺序,确保依赖关系正确处理。同时,介绍了如何使用@PostConstruct进行初始化操作,并通过自定义Scope实现属性的动态加载与更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@DependsOn注解可以控制bean的加载顺序 

当A依赖B时,因为并不知道A与B谁先优先加载,可以再A类上添加此注解去依赖B

这时当先加载了A 时,会先实例化B并且注入属性,但是B中的Bean并不会加载。

例子1:

实现@Value属性注入从数据库加载的数据。

1、从数据库拿配置

@Configuration
public class DbConfig {
    /**
     * 这个就是查询service
     */
    @Autowired
    private DbService dbService;
    /**
     * spring 所有的变量都存在这里面
     * 解析${xxx}时用resolvePlaceholders
     */
    @Autowired
    private StandardEnvironment environment;

    /**
     * 注意这个注解@PostConstruct 执行完实例化后执行此注解标注方法
     * 不能用@Bean代替
     */
    @PostConstruct
    public void getConfig() {
        //获取配置实体
        MyDbProperties dbConfig = dbService.getConfig();
        Map<String, Object> properties = new HashMap<>();
        //配置到properties
        properties.put("user.name", dbConfig.getName());
        properties.put("user.pwd", dbConfig.getPwd());
        //构造MapPropertySource
        MapPropertySource mailPropertySource = new MapPropertySource("user", properties);
        //放入环境变量
        environment.getPropertySources().addFirst(mailPropertySource);
    }

}

2、用

@Component
@DependsOn("dbConfig")//这个注解表示需要依赖其他类,优先实例化其他类
public class OtherClass  {

	/**
	 * 直接用即可
	 */
	private String value;
	@Value("${user.name}")
	private void setValue(String value){
		this.value=value;
	}


}

 

总结:

1、DependsOn注解可以控制bean加载顺序

2、PostConstruct注解在实例化完成类之后就执行

 

例子2:

动态修改数据库配置,@Value注解动态加载属性

1、自定义scope注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Scope(MyBeanRefreshScope.SCOPE_REFRESH)
@Documented
public @interface MyRefreshScope {
    /**
     * TARGET_CLASS类型才能为标注此注解的类生成代理对象
     */
    ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

2、scope处理类

public class MyBeanRefreshScope extends GenericScope {

    public static final String SCOPE_REFRESH = "MY";

    private static final MyBeanRefreshScope INSTANCE = new MyBeanRefreshScope();

    /**
     * 和注解value要一致
     */
    public MyBeanRefreshScope(){
        super.setName(SCOPE_REFRESH);
    }

    public static MyBeanRefreshScope getInstance(){
        return INSTANCE;
    }

    //重新加载dbConfig类,获取修改后的配置
    public void clear() {
        ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) SpringContextUtils.getApplicationContext();
        BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry)applicationContext.getBeanFactory();
        beanFactory.removeBeanDefinition("dbConfig");
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DbConfig.class);
        BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
        beanFactory.registerBeanDefinition("dbConfig",beanDefinition);
        applicationContext.getBean("dbConfig", DbConfig.class);
    }

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        this.clear();
        //把标注注解的类重新加载,这样就会重新赋值@Value值
        super.destroy();
        return super.get(name,objectFactory);
    }

}

3、注册自定义scope

@Component
public class ScopeBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.registerScope(MyBeanRefreshScope.SCOPE_REFRESH,MyBeanRefreshScope.getInstance());
    }
}

4、用

@Component
@DependsOn("dbConfig")//这个注解表示需要依赖其他类,优先实例化其他类
public class OtherClass  {
	/**
	 * 直接用即可
	 */
	private String value;
	@Value("${user.name}")
	private void setValue(String value){
		this.value=value;
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jackson陈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值