Java 无法从BeanPostProcessor中的占位符获取值
我将Spring与Spring Boot BOM 2.4.0附带的遗留Tomcat应用程序(不是Spring Boot)一起使用,问题与之类似,但我有一个特定的案例 如果我有一个具有Java 无法从BeanPostProcessor中的占位符获取值,java,spring,Java,Spring,我将Spring与Spring Boot BOM 2.4.0附带的遗留Tomcat应用程序(不是Spring Boot)一起使用,问题与之类似,但我有一个特定的案例 如果我有一个具有@Value(${spring.kafka.maximumRequestSize:15728640})的依赖类和以下内容 @Configuration @Order public class KafkaTracingDecorator implements ApplicationContextAware {
@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);
}
}
当创建WebApplicationContext时,我得到由以下原因引起的:java.lang.NumberFormatException:For输入字符串:“${spring.kafka.maximumRequestSize:15728640}”
即使我不使用该值,也会发生这种情况,因此它不会进入方法
@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引导的预期效果相同,因此可能与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添加:链接到GitHub问题,以防它是一个bug而不是使用问题。您需要通过注册PropertySourcesPlaceholderConfigurer
bean来更新Decorator
类,以解决您的问题
根据:
PropertyPlaceHolderConfiguration是占位符配置支持的子类。此子类有助于根据本地属性和/或系统属性和环境变量解析占位符
因此,配置此bean将从类路径加载应用程序.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
...
.....
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
运行在采用的OpenJDK 11.0.6上的Tomcat 8.5.57的控制台日志:
spring.kafka.maximumRequestSize=15728640
...
.....
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
在构建WebApplicationContext时启动。更新了Q以包含factCan不能做到这一点,它不是一个开源项目,我正在尝试创建一个MVCE来显示它,但它在MVCE本身工作。Thx我基本上调整了Spring Boot starter,使之成为Tomcat+WAR部署,希望问题会显现出来。我注意到它已经在Spring Boot上工作了。我确实添加了MVCE,现在证明了失败。在一只停靠的雄猫身上。你有答案吗?是的,MVCE会处理这个更改,并在更大的项目上尝试。我想问另一个问题,但是你可以使用哪种资源让“环境变量”设置属性。这个问题的第二部分,支持bean需要在这个配置中定义,还是可以在外部定义?我刚刚测试过,它可以是外部的,将它分开可能是一个更好的答案,而不是嵌入到decorator中。所以我注意到您使用的是静态的,我在MVCE上测试过,它看起来不需要static@ArchimedesTrajano是 啊但如果没有静电干扰,数据就不会被采集。我的情况是零。它是否从您的案例中的属性中获取了正确的价值?