java - 无法从 BeanPostProcessor 中的占位符获取值
问题描述
我正在将 Spring 与 Spring Boot BOM 2.4.0 附带的遗留 Tomcat 应用程序(不是 Spring Boot)一起使用,问题类似于Spring Expression Language not working但我有一个具体案例。
如果我有一个具有@Value("${spring.kafka.maximumRequestSize:15728640}")
以下内容的依赖类
@Configuration
@Order
public class KafkaTracingDecorator implements ApplicationContextAware {
private KafkaTracing kafkaTracing;
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
kafkaTracing = applicationContext.getBean(KafkaTracing.class);
}
}
有用。以下也有效,但我没有在后处理器上做任何事情
@Configuration
@Order
public class KafkaTracingDecorator implements BeanPostProcessor, ApplicationContextAware {
@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
return bean;
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
// kafkaTracing = applicationContext.getBean(KafkaTracing.class);
}
}
但是当我尝试实现这样BeanPostProcessor
的装饰器模式时
@Configuration
@Order
public class KafkaTracingDecorator implements BeanPostProcessor, ApplicationContextAware {
private KafkaTracing kafkaTracing;
@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
if (bean instanceof KafkaProducer) {
return kafkaTracing.producer((KafkaProducer) bean);
} else if (bean instanceof KafkaConsumer) {
return kafkaTracing.consumer((KafkaConsumer) bean);
} else {
return bean;
}
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
kafkaTracing = applicationContext.getBean(KafkaTracing.class);
}
}
我Caused by: java.lang.NumberFormatException: For input string: "${spring.kafka.maximumRequestSize:15728640}"
在创建 WebApplicationContext 时得到。
即使我不使用该值也会发生这种情况,因此它不会进入方法
@Configuration
@Order
public class KafkaTracingDecorator implements BeanPostProcessor, ApplicationContextAware {
private KafkaTracing kafkaTracing;
@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
return bean;
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
kafkaTracing = applicationContext.getBean(KafkaTracing.class);
}
}
这是一个非常简化的示例,它也以同样的方式失败:
@Configuration
public class KafkaTracingDecorator implements BeanPostProcessor {
@Value("${spring.kafka.maximumRequestSize:15728640}")
private int maxRequestSize;
}
(请注意,这在 Spring Boot 上按预期工作,因此可能与 Spring 的非引导使用有关)
导致错误的部分堆栈跟踪未列出任何自定义代码:
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:270)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:761)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:566)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:401)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:292)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4689)
MVCE 添加:https ://github.com/trajano/spring-beanpostproc-mvce链接到 GitHub 问题,以防它是错误https://github.com/spring-projects/spring-framework/issues/26571而不是使用问题。
解决方案
您需要Decorator
通过注册PropertySourcesPlaceholderConfigurer
bean 来更新类来解决您的问题。
根据Spring Docs on PropertyPlaceholderConfigurer:
PropertyPlaceholderConfigurer是PlaceholderConfigurerSupport的子类。此子类有助于
${...}
根据本地属性和/或系统属性和环境变量解析占位符。
因此,配置此 bean 将从类路径加载application.properties,它将能够解析${..}
用于@Value
注释的实际值集。
更新的装饰类:
@Configuration
public class Decorator implements BeanPostProcessor {
@Value("${spring.kafka.maximumRequestSize}")
private int maxRequestSize;
@Bean
public static PlaceholderConfigurerSupport placeholderConfigurerSupport() {
PlaceholderConfigurerSupport support = new PropertySourcesPlaceholderConfigurer();
support.setLocations(new ClassPathResource("application.properties"));
return support;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(maxRequestSize);
return bean;
}
}
应用程序属性:
spring.kafka.maximumRequestSize=15728640
在AdoptedOpenJDK 11.0.6上运行的Tomcat 8.5.57的控制台日志:
...
.....
INFO: Initializing Spring root WebApplicationContext
Feb 20, 2021 9:21:41 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization started
15728640
Feb 20, 2021 9:21:41 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext initialized in 518 ms
Feb 20, 2021 9:21:41 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
Feb 20, 2021 9:21:41 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 1419 ms
推荐阅读
- keyframe - 为什么当我们在时间轴中添加或删除顶点后形状会发生变化
- java - Optaplanner 中的建模活动调度
- java - 正则表达式不起作用将拖尾报价
- python - 有条件格式化时用于 Python TypeError 的 Openpyxl
- swift - UIView 的部分屏幕截图被 UIBezierPath / CGPath
- python - 熊猫条件列添加
- github - Git Flow CLI 与 GitHub 保护的分支不兼容
- c++ - 指向指向 C++ 中结构的指针数组的指针
- certificate - 在带有 tizen studio 2.3 的可穿戴设备 Gear s3 上运行时出现证书错误
- python - Python:函数映射的内存问题