【发布时间】:2022-08-22 14:36:22
【问题描述】:
我想将配置数据注入 Spring Boot 应用程序。我查看了@Value,这将是完美的,但文本的格式不适合我的用例(我希望格式与我们当前在 JEE 中的实现向后兼容,它将与我们的 SpringBoot 实现并列,并且有很多目前使用这种方法的代码)。
因此,我不想说 @Configuration(\"${somevalue}\") 和正在注入的配置,而是说 @Configuration(\"somevalue\") 并且它仍然被注入,而不是仅仅放置 \"somevalue\"变量中的文本。
其中 Configuration 是 @Value 的别名,如下所示:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Value(\"\")
public @interface Configuration {
@AliasFor(annotation=Value.class, attribute=\"value\")
String value() default \"\";
}
我确实尝试更改占位符的前后后缀,因此它们是 \"\" 但这导致 SpringBoot 根本无法启动。
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
p.setIgnoreResourceNotFound(true);
p.setPlaceholderPrefix(\"\");
p.setPlaceholderSuffix(\"\");
p.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);
return p;
}
我还尝试在运行时更改注释,以便扫描类路径并将所有没有 ${...} 的注释更改为 ${...},但这也不起作用,因为代理处理程序值每次都会更改您进行类查找,这意味着您更改了正在查看的实例,但没有更改 Spring 使用的实例。
所以我想我会有自己的@Value 实现,像这样使用:
@RestController
public class PingResource {
@Inject
public PingResource(@Configuration(\"someValue\") String someValue) {
...
}
}
使用这样的 Bean 生产者:
@Configuration
public class ConfigurationProducer {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public String getString(final InjectionPoint injectionPoint) {
....
}
}
但是 Spring 中的限定符看起来不支持注释,所以它找不到 bean,我得到了这个异常:
NoSuchBeanDefinitionException: No qualifying bean of type \'java.lang.String\' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@bob.Configuration(value=someValue)}
如果我从参数中取出注释,那么它会找到 bean 工厂并且一切都很好......除了我不知道我应该注入什么配置值,因为没有注释可以告诉我。
有点卡住了,我查看了 Spring 代码,看看它是如何实现 @Value 的,看看我是否可以重新创建它,但这是一个很难理解的老鼠窝。
任何帮助或建议下一步该去哪里解决这个问题,感觉就像我非常接近,但只是错过了一些我不知道的 Spring 魔法。
非常感谢
-
您可以使用反射来更改 spring bean 中的字段值。那对你有用吗?
-
是的,我尝试使用: InvocationHandler handler = Proxy.getInvocationHandler(annotation);字段 f = handler.getClass().getDeclaredField(\"memberValues\"); f.setAccessible(true); Map<String, Object> memberValues = (Map<String, Object>) f.get(handler); memberValues.put(key, newValue);如果您使用相同的“getDeclaredConstructors()”返回变量获取注释值,它的工作原理是。但是,当您再次执行此操作时,更改将丢失。我认为这是因为每次您进行查找时代理值都不同,因此任何更改都会丢失。
-
您可以使用 Springs 应用程序上下文来访问所有 Spring bean,然后对其进行操作。 for (String bean : applicationContext.getBeanDefinitionNames()) ... 然后单独访问它们。不过只适用于春豆的田地
标签: java spring spring-boot jakarta-ee