Lazy-initialized Beans

默认情况下,Spring ApplicationContext 会预实例化所有单例 Bean。通常这很理想,因为它可以立即发现错误。但是,可以通过标记 Bean 为延迟初始化来阻止预实例化。延迟初始化的 Bean 仅在首次请求时创建实例,而不是在启动时。ただし、延迟初始化 Bean 如果依赖于非延迟初始化单例 Bean,则它们将在启动时创建。可以通过使用 @Lazy 注释或修改 XML 配置来控制单组 Bean 的延迟初始化行为。

默认情况下,"@70" 实现作为初始化过程的一部分急切创建和配置所有 "@71" Bean。通常,这种预例化是可取的,因为配置或周围环境中的错误会立即被发现,而不是在数小时甚至数天后。如果不希望出现这种行为,可以通过将 Bean 定义标记为延迟初始化来阻止预例化单例 Bean。延迟初始化 Bean 告诉 IOC 容器在首次请求 Bean 实例时创建实例,而不是在启动时创建。

此行为由 @Lazy 注释或 <bean/> 元素上的 lazy-init 属性控制,如下例所示:

  • Java

  • Kotlin

  • Xml

@Bean
@Lazy
ExpensiveToCreateBean lazy() {
	return new ExpensiveToCreateBean();
}

@Bean
AnotherBean notLazy() {
	return new AnotherBean();
}
@Bean
@Lazy
fun lazy(): ExpensiveToCreateBean {
	return ExpensiveToCreateBean()
}

@Bean
fun notLazy(): AnotherBean {
	return AnotherBean()
}
<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>

<bean name="notLazy" class="com.something.AnotherBean"/>

当`ApplicationContext` 使用前面的配置时,lazy bean 在`ApplicationContext` 启动时不会急切地预实例化,而`notLazy` bean 会急切地预实例化。

但是,当延迟初始化 Bean 是一个不是延迟初始化的单例 Bean 的依赖时,ApplicationContext 会在启动时创建延迟初始化 Bean,因为它必须满足单例的依赖关系。延迟初始化 Bean 被注入到在别处的一个不是延迟初始化的单例 Bean 中。

您也可以通过在带有 @Configuration 注释的类上使用 @Lazy 注释或在 XML 中通过 <beans/> 元素上的 default-lazy-init 属性来控制一组 bean 的延迟初始化,如下所示:

  • Java

  • Kotlin

  • Xml

@Configuration
@Lazy
public class LazyConfiguration {
	// No bean will be pre-instantiated...
}
@Configuration
@Lazy
class LazyConfiguration {
	// No bean will be pre-instantiated...
}
<beans default-lazy-init="true">

	<!-- No bean will be pre-instantiated... -->
</beans>