SpringBoot2.动态@Value实现

本文介绍了如何在SpringBoot2中实现在运行时动态改变@Value注解的值,通过BeanPostProcessor接口获取使用@Value注解的bean,并在需要时更新其字段值,以实现类似配置中心的功能。文章提供了实现步骤和部分代码示例。
摘要由CSDN通过智能技术生成

title: SpringBoot2.动态@Value实现

前言

前面文章有详细描述过各个不同阶段对于bean的扩展接口
所以今天就基于BeanPostProcessor实现Spring中的@Value注解值动态变化
基于上面也可以实现一个配置中心,比如说Apollo
具体的实现步骤分为如下几步
1.通过BeanPostProcessor取得有使用@Value注解的bean,并存储到map中
2.动态修改map中的bean字段的值

获取bean

首先写一个类实现BeanPostProcessor接口,只需要使用其中的一个函数就可以。前后都可以用来实现,并不影响最终的使用,因为咱们只是需要bean的实例。
接下来看一下具体实现代码

package com.allen.apollo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

@Configuration
public class SpringValueProcessor implements BeanPostProcessor {
   
    private final PlaceholderHelper placeholderHelper = new PlaceholderHelper();

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   
        if (beanName.equals("springValueController")) {
   
            Class obj = bean.getClass();
            List<Field> fields = findAllField(obj);
            for (Field field : fields) {
   
                Value value = field.getAnnotation(Value.class);
                if (value != null) {
   
                    Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value());
                    for (String key : keys) {
   
                        SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field, false);
                        SpringValueCacheMap.map.put(key, springValue);
                    }
                }
            }
        }
        return bean;
    }

    private List<Field> findAllField(Class clazz) {
   
        final List<Field> res = new LinkedList<>();
        ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() {
   
            @Override
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
   
                res.add(field);
            }
        });
        return res;
    }
}

上面的代码咱们就已经拿到了SpringValueController这个实例bean并存储到了map当中,下面看一下测试代码

  /**
   * cache  field,存储bean 字段
   */
package com.allen.apollo;

import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;

public class SpringValueCacheMap {
   
    public static final Multimap<String, SpringValue> map = LinkedListMultimap.create();
}


 package com.allen.apollo;


import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

import org.springframework.core.MethodParameter;


public class SpringValue {
   

    private MethodParame
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值