Spring中配置lazy-init=true仍触发构造方法,如何避免启动时调用?
lazy-init="true"但构造方法启动时仍执行的问题 这种情况我碰到过好几次,大概率是你的abc bean被其他非懒加载的组件依赖了,或者在启动阶段被主动获取了,下面给你一步步排查和解决的方法:
一、排查核心原因
1. 被其他非懒加载bean依赖
Spring的懒加载规则是:如果一个懒加载bean被非懒加载的bean直接/间接依赖,Spring会在启动时提前初始化这个懒加载bean,来满足依赖关系。比如你有一个这样的bean:
<bean id="xyz" class="x.y.z.ServiceClass"> <property name="util" ref="abc"/> </bean>
因为xyz默认是非懒加载的(lazy-init默认是false),启动时Spring初始化xyz时必须先创建abc实例,所以abc的构造方法就会被触发。
2. 启动阶段主动获取了该bean
如果你的启动代码(比如Spring容器初始化完成后,通过ApplicationContext.getBean("abc")主动获取这个bean),或者在某个@PostConstruct方法、ServletContextListener里调用了获取abc的逻辑,也会导致它提前初始化。
3. 被depends-on引用
如果有其他bean配置了depends-on="abc",且这个bean是非懒加载的,那么Spring会先初始化abc来满足依赖顺序要求:
<bean id="xyz" class="x.y.z.AnotherClass" depends-on="abc"/>
二、对应的解决方案
1. 处理依赖关系
- 方案一:把依赖
abc的bean也设置为懒加载
如果xyz这个bean也不需要在启动时初始化,直接给它加上lazy-init="true":<bean id="xyz" class="x.y.z.ServiceClass" lazy-init="true"> <property name="util" ref="abc"/> </bean> - 方案二:使用延迟依赖注入(XML方式)
如果xyz必须非懒加载,但abc只在某个方法调用时才需要,可以用Spring的lookup-method来实现延迟获取:
对应的<bean id="abc" class="a.b.c.UtilClass" lazy-init="true"/> <bean id="xyz" class="x.y.z.ServiceClass"> <lookup-method name="getUtilClass" bean="abc"/> </bean>ServiceClass需要定义一个抽象方法:public abstract class ServiceClass { public void doSomething() { // 只有调用这个方法时才会初始化abc UtilClass util = getUtilClass(); util.doWork(); } protected abstract UtilClass getUtilClass(); }
2. 移除启动阶段的主动获取
检查你的启动相关代码,比如:
- Spring容器初始化后的回调逻辑
@PostConstruct注解的方法- 自定义的
ApplicationListener实现
确保没有在这些地方调用getBean("abc"),把获取逻辑移到真正需要使用abc的业务方法里。
3. 调整depends-on配置
如果其他bean的depends-on是不必要的,直接移除这个配置;如果必须保留,那要么把依赖的bean设置为懒加载,要么接受abc提前初始化(或者重新设计依赖关系)。
三、验证方法
你可以开启Spring的debug日志,查看容器初始化时的bean创建顺序,日志里会显示Creating instance of bean 'abc'的触发原因,比如是因为某个依赖bean的初始化导致的,这样就能精准定位问题。
内容的提问来源于stack exchange,提问作者slayer

