gpt4 book ai didi

java - 懒加载 spring bean

转载 作者:搜寻专家 更新时间:2023-11-01 01:20:12 24 4
gpt4 key购买 nike

如果一个bean被延迟加载,那么延迟加载bean内部定义的所有bean都会被延迟加载吗? (即使它们没有定义@Lazy)

这里是测试项目: https://github.com/madhur/conditional-property-test/blob/master/src/main/java/com/example/demo/EventPublishService.java

我有这些 bean :

@Service
@ConditionalOnProperty(
name = {"publish.feed.events"},
havingValue = "true"
)
public class EventPublishService {

@Autowired
private KafkaPublisher kafkaPublisher;

}

///////////////////

@Service
public class EventService {

@Autowired
@Lazy
private EventPublishService eventPublishService;

@Value("${publish.feed.events:false}")
private boolean isPublishEvents;
}

////////////////////////

@Component
public class KafkaPublisher {

@Value("${kafka.producer.financial_feed.topic}")
private String financeFeedTopic;
}

我的任何 application.properties 只有一个属性,

publish.feed.events=false

因为,我没有加载 EventPublishService beans(因为该属性为 false),我希望依赖 bean KafkaPublisher 也不应该被加载。但是,我在启动时收到错误,这意味着 KafkaPublisher bean 正在加载,即使 EventPublishService bean 没有加载。

如何确保不加载 KafkaPublisher bean?因此,对于不需要 EventPublishService bean 的任何人来说,属性不应该是强制要求的吗?

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kafkaPublisher': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'kafka.producer.financial_feed.topic' in value "${kafka.producer.financial_feed.topic}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:379) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1344) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:578) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at com.example.demo.DemoApplication.main(DemoApplication.java:17) [main/:na] Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'kafka.producer.financial_feed.topic' in value "${kafka.producer.financial_feed.topic}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:172) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:237) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:211) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:839) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1086) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
... 16 common frames omitted

最佳答案

作为stated in the doc ,

Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created

因此,如果将 @Lazy 放在 @Autowired 上并不重要,bean 将在启动时创建 只要 bean 本身不是定义惰性:

@Component
public class KafkaPublisher {
...
}

如果你想延迟初始化这个bean,把 @Lazy 放在上面。如果你希望bean注入(inject)的过程是惰性的,把@Lazy放在@Autowired上,就这么简单。

延迟初始化一组相关 bean 可以通过在 @Configuration 类中声明它们并标记配置 @Lazy 来实现。但是,请注意所有声明的 bean 将在 @Configuration 类初始化后立即初始化。

@Lazy
@Configuration
@ComponentScan(...) // will be lazily initialized with config
public class LazyConfiguration {

@Bean
public SomeBean beanName() { // will be lazily initialized with config
return new SomeBean();
}

@Bean
public OtherBean beanName() { // will be lazily initialized with config
return new OtherBean();
}
}

但是,当使用 @ComponentScan 时,请确保要延迟初始化的 bean(即 @Service@Component 等)尚未被其他上下文扫描。如果是,将它们添加为扫描该上下文的排除对象。


下面的过时答案,出于历史目的(在 OP 完全改变问题之前):

在 beans 内部声明 beans 被认为不是一个好的做法,但是如果你将 @Configuration 标记为惰性的,那么它里面的所有 beans 都会被惰性初始化,如 @Lazy 的 javadoc:

If Lazy is present on a @Configuration class, this indicates that all @Bean methods within that @Configuration should be lazily initialized.

如果您所说的“内部定义的 beans” 实际上是指注入(inject)点,例如 @Autowired,javadoc 也有相应的答案:

Lazy annotation may also be placed on injection points marked with Autowired or Inject: In that context, it leads to the creation of a lazy-resolution proxy for all affected dependencies, as an alternative to using ObjectFactory or Provider.

然而,实际的 Autowiring bean 将被急切地初始化(如果没有标记为 @Lazy)。在这种情况下,注入(inject)本身将是惰性的。

否则,请说明你的意思。

关于java - 懒加载 spring bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50041216/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com