在spring中我们可以用@value注解将配置文件中的值注入到对象属性上。同样,在springboot中我们可以在类上使用@ConfigurationProperties注解完成同样的功能。
但对于类变量,即用static修饰的变量也想注入时,@value需要写在set方法上,而@ConfigurationProperties无法对静态属性进行注入。这就不得不为每个属性都加入一个set方法,十分枯燥,繁琐。
闲来无事,想对@ConfigurationProperties注解进行增强,让其可以为静态属性赋值,但又不失简便。
这里我主要是写了两个类,一个是注解类@AutowiredStaticProperty,用它代替@ConfigurationProperties对属性赋值,用法和@ConfigurationProperties一样。。另一个是AutowiredStaticPropertyPostProcessor,作用是在容器启动时解析@AutowiredStaticProperty注解,并为对象赋值。
用法上,只需要将两个类考到项目中,在需要注入到类上加上@AutowiredStaticProperty即可。下面是代码
@AutowiredStaticProperty
package com.zhen.util;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.core.annotation.AliasFor; import org.springframework.stereotype.Component;
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @ConfigurationProperties @Component public @interface AutowiredStaticProperty {
@AliasFor(annotation = ConfigurationProperties.class) String prefix() default ""; }
|
AutowiredStaticPropertyPostProcessor
/** * */ package com.zhen.util;
import java.lang.reflect.Field; import java.lang.reflect.Modifier;
import org.springframework.beans.BeansException; import org.springframework.beans.TypeConverter; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component;
/** * 自动注入静态属性后置处理器 * 对注解了 @AutowiredStaticProperty 的类自动装配静态属性 */ @Component public class AutowiredStaticPropertyPostProcessor implements BeanPostProcessor, ApplicationContextAware {
private ApplicationContext applicationContext;
/** * 在bean的初始化方法(afterPropertiesSet,init-method)之前调用。不影响后续spring对bean属性赋值操作 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 未添加注解的默认spring处理 boolean annotationPresent = bean.getClass() .isAnnotationPresent(AutowiredStaticProperty.class); if (!annotationPresent) { return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); }
// 获取类型转换器 转换类型 (无法获取类型转换器时由spring自己处理) ConfigurableListableBeanFactory configurableListableBeanFactory = getConfigurableListableBeanFactory(); if (configurableListableBeanFactory == null) { return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); }
Environment environment = applicationContext.getEnvironment(); TypeConverter typeConverter = configurableListableBeanFactory.getTypeConverter();
AutowiredStaticProperty autowiredStaticPropertyAnnotation = bean.getClass() .getAnnotation(AutowiredStaticProperty.class); String prefix = autowiredStaticPropertyAnnotation.prefix();
// 赋值 Field[] declaredFields = bean.getClass().getDeclaredFields(); for (Field field : declaredFields) { int modifiers = field.getModifiers();
// 非静态变量由系统赋值 if (!Modifier.isStatic(modifiers)) { continue; } if (Modifier.isPrivate(modifiers)) { field.setAccessible(true); }
String propertyName = field.getName(); String key = prefix == null ? propertyName : prefix.concat(".").concat(propertyName); String value = environment.getProperty(key); Class<?> type = field.getType(); Object valueToUse = typeConverter.convertIfNecessary(value, type); try { field.set(bean, valueToUse); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return bean; }
/** * 获取bean工厂 * * @return */ private ConfigurableListableBeanFactory getConfigurableListableBeanFactory() { if (applicationContext instanceof ConfigurableApplicationContext) { return ((ConfigurableApplicationContext) applicationContext).getBeanFactory(); } return null; }
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
|
测试类:
/** * */ package com.zhen.model;
import java.util.List; import java.util.Map;
import com.zhen.util.AutowiredStaticProperty;
import lombok.Data;
@AutowiredStaticProperty(prefix = "houzhen") public class TestModel { public static Long name;
private String age;
private List<String> list;
private Map<String, String> maps; }
|
扩展是基于springboot的,只测试了几种简单类型,对于复杂类型如果需要可以自行扩展。欢迎指正
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南