Spring Boot如何为自定义Indexable注解的indexName添加配置前缀
嘿,我明白你想做什么——给自定义注解@Indexable的indexName属性加上application.yml里配置的前缀对吧?不过Spring默认不会自动解析注解属性里的${}占位符,得咱们手动搞一下,我给你捋清楚步骤:
1. 先确认你的application.yml配置没问题
首先确保你的前缀配置是正确的格式:
application: elasticsearch: prefix: dev_
2. 写个占位符解析工具类
我们需要借助Spring的Environment来读取配置值,写个工具类专门处理占位符解析:
import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; @Component public class PlaceholderResolver { private final Environment environment; // 构造注入Environment,Spring会自动提供这个实例 public PlaceholderResolver(Environment environment) { this.environment = environment; } public String resolve(String rawValue) { // 先判断是不是占位符格式 if (rawValue == null || !rawValue.startsWith("${") || !rawValue.endsWith("}")) { return rawValue; } // 提取占位符里的配置键 String configKey = rawValue.substring(2, rawValue.length() - 1); // 读取配置值,找不到的话返回原字符串作为 fallback return environment.getProperty(configKey, rawValue); } }
3. 在使用注解的地方解析占位符
不管你是在处理索引的服务里,还是在Bean初始化阶段,都可以用这个工具类解析indexName的值。举个服务类的例子:
import org.springframework.stereotype.Service; @Service public class IndexManagementService { private final PlaceholderResolver placeholderResolver; public IndexManagementService(PlaceholderResolver placeholderResolver) { this.placeholderResolver = placeholderResolver; } public void setupIndexForClass(Class<?> targetClass) { if (targetClass.isAnnotationPresent(Indexable.class)) { Indexable indexable = targetClass.getAnnotation(Indexable.class); // 解析注解里的原始indexName String resolvedIndexName = placeholderResolver.resolve(indexable.indexName()); // 这里就可以用解析后的名字做创建索引、绑定映射等操作了 System.out.println("最终索引名:" + resolvedIndexName); // 会输出 dev_address } } }
4. (可选)在Bean初始化时自动解析
如果想在Bean创建的时候就自动处理注解的占位符,可以写个BeanPostProcessor:
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class IndexableAnnotationProcessor implements BeanPostProcessor { private final PlaceholderResolver placeholderResolver; public IndexableAnnotationProcessor(PlaceholderResolver placeholderResolver) { this.placeholderResolver = placeholderResolver; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Class<?> beanClass = bean.getClass(); if (beanClass.isAnnotationPresent(Indexable.class)) { Indexable indexable = beanClass.getAnnotation(Indexable.class); String resolvedName = placeholderResolver.resolve(indexable.indexName()); // 这里可以把解析后的索引名存起来,或者做初始化操作 System.out.println("Bean " + beanName + "对应的索引名:" + resolvedName); } return bean; } }
这样一来,你原来的注解写法完全不用改:
@Indexable(indexName = "${application.elasticsearch.prefix}address") public class Address implements Serializable { } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Indexable { String indexName() default ""; }
只要Spring能扫描到咱们写的工具类和处理器,运行时就能自动把${application.elasticsearch.prefix}替换成yml里的dev_,最终得到dev_address的索引名啦。
内容的提问来源于stack exchange,提问作者Aymen Kanzari
相关产品推荐
相关产品推荐

