延迟加载spring bean

时间:2018-04-26 10:56:45

标签: java spring

如果一个bean被延迟加载,那么在懒惰加载的bean中定义的所有bean都会被延迟加载吗? (即使他们没有定义@Lazy)

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

我有这些豆子:

@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 bean(因为属性为false),我希望不应该加载依赖bean KafkaPublisher。但是,我在启动时收到错误,这意味着即使没有加载EventPublishService bean,KafkaPublisher bean也会被加载。

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

  

org.springframework.beans.factory.BeanCreationException:错误   用名称' kafkaPublisher创建bean&#39 ;:注入自动装配   依赖失败;嵌套异常是   java.lang.IllegalArgumentException:无法解析占位符   ' kafka.producer.financial_feed.topic'价值   " $ {kafka.producer.financial_feed.topic}"           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:379)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1344)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:578)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.AbstractBeanFactory.lambda $ doGetBean $ 0(AbstractBeanFactory.java:317)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)   〜[弹簧上下文5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)   〜[弹簧上下文5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)   [弹簧引导2.0.1.RELEASE.jar:2.0.1.RELEASE]           在org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395)   [弹簧引导2.0.1.RELEASE.jar:2.0.1.RELEASE]           在org.springframework.boot.SpringApplication.run(SpringApplication.java:327)   [弹簧引导2.0.1.RELEASE.jar:2.0.1.RELEASE]           在org.springframework.boot.SpringApplication.run(SpringApplication.java:1255)   [弹簧引导2.0.1.RELEASE.jar:2.0.1.RELEASE]           在org.springframework.boot.SpringApplication.run(SpringApplication.java:1243)   [弹簧引导2.0.1.RELEASE.jar:2.0.1.RELEASE]           在com.example.demo.DemoApplication.main(DemoApplication.java:17)   [main /:na]引起:java.lang.IllegalArgumentException:不能   解决占位符' kafka.producer.financial_feed.topic'价值   " $ {kafka.producer.financial_feed.topic}"           在org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:172)   〜[弹簧芯5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)   〜[弹簧芯5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:237)   〜[弹簧芯5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:211)   〜[弹簧芯5.0.5.RELEASE.jar:5.0.5.RELEASE]           at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda $ processProperties $ 0(PropertySourcesPlaceholderConfigurer.java:175)   〜[弹簧上下文5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:839)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1086)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           在org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373)   〜[弹簧豆-5.0.5.RELEASE.jar:5.0.5.RELEASE]           ...省略了16个常见帧

1 个答案:

答案 0 :(得分:11)

作为stated in the doc

  

创建容器时创建单例范围并设置为预先实例化(默认值)的Bean

因此,如果将@Lazy放在@Autowired上并不重要,只要bean本身没有定义为懒惰,就会在启动时创建bean

@Component
public class KafkaPublisher {
    ...
}

如果您想要懒惰地初始化此bean,请将 @Lazy 放在其上。如果你想让bean注入过程变得懒惰,那就把@Lazy放在@Autowired上,就这么简单。

通过在@Configuration类中声明它们并标记配置@Lazy,可以实现Lazily初始化一组相关bean。但是,请注意,只要初始化@Configuration类,就会初始化所有声明的bean。

@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完全改变问题之前):

在bean中声明bean不被认为是一种好习惯,但是如果你将@Configuration标记为懒惰,那么它内部的所有bean都会被懒惰地初始化,如@Lazy中所述' javadoc:

  

如果@Configuration类中存在Lazy,则表示全部   @Configuration中的@Bean方法应该被懒惰地初始化。

如果"在#34; 中定义的bean实际上意味着注入点,例如@Autowired,javadoc也有答案:

  

懒惰注释也可以放在标有的注入点上   自动装配或注入:在这种情况下,它会导致创建一个   作为替代方案,所有受影响的依赖项的延迟解析代理   使用ObjectFactory或Provider。

但是,实际的autowired bean将被急切地初始化(如果没有标记为@Lazy)。在这种情况下注射本身就是懒惰的。

否则,请澄清你的意思。