Spring--初始化bean:InitializingBean、init-method
1、Spring为bean提供了两种初始化bean的方式,实现InitializingBean接口或者通过在XML配置文件中添加init-method的方式,这两种方式可以同时使用。
2、实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率要高一点,但是init-method方式消除了对spring的依赖。
3、如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。
InitializingBean
InitializingBean是Spring提供的拓展性接口,InitializingBean接口为bean提供了属性初始化后的处理方法,它只有一个afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。
作用
我们直接通过查看源码注释可知 -- InitializingBean源码注释翻译
示例
自定义MyInitializingBean实现InitializingBean接口

1 @Component 2 public class MyInitializingBean implements InitializingBean { 3 4 @Override 5 public void afterPropertiesSet() throws Exception { 6 System.out.println("implements InitializingBean......"); 7 } 8 9 }
运行结果如下:
这说明在 spring 初始化 bean 的时候,如果 bean 实现了 InitializingBean 接口,会自动调用 afterPropertiesSet 方法。
问题:如果bean实现了InitializingBean接口,并且同时配置了init-method,会怎么样?
配置init-method
我们可以通过XML文件的方式或者更简洁的@Bean注解的方式去配置init-methodf方法。
一. 通过XML文件方式配置init-method方法
项目的resource下新建xml文件
在配置文件中加入 init-method="testInit"。
通过配置类加载 xml 配置文件

/** * 通过配置类加载 xml 配置文件 * @author JustJavaIt * @date 2022/9/10 15:20 */ @ImportResource(locations = "classpath:bean.xml") @Configuration public class WebMvcConfig { }
然后在MyInitializingBean中添加初始化方法testInit()

注意注释掉@Compoment,否者会报bean已经被定义了。
二. 通过@Bean的方式配置init-method方法

1 @Component 2 public class MyInitializingBean implements InitializingBean { 3 4 @Override 5 public void afterPropertiesSet() throws Exception { 6 System.out.println("implements InitializingBean......"); 7 } 8 9 public void testInit(){ 10 System.out.println("init-method......"); 11 } 12 13 /** 14 * 相当于在xml配置文件中加入 15 * <bean id="myInitializingBean" class="类路径" init-method="testInit"></bean> 16 * @return 17 */ 18 @Bean(initMethod = "testInit") 19 public MyInitializingBean test() { 20 return new MyInitializingBean(); 21 } 22 }
最终运行结果
由结果可看出,在 spring 初始化 bean 的时候,如果该 bean 是实现了 InitializingBean 接口,并且同时在配置文件中指定了 init-method,系统则是先调用 afterPropertiesSet 方法,然后再调用 init-method 中指定的方法。
invokeInitMethods源码分析
通过查看Spring加载bean的源码类AbstractAutowiredCapableBeanFactory可以看出其中的奥妙,AbstractAutowiredCapableBeanFactory类中的invokeInitMethods说的非常清楚,如下:
1 protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { 2 //判断该bean是否实现了实现了InitializingBean接口,如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法 3 boolean isInitializingBean = (bean instanceof InitializingBean); 4 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { 5 if (logger.isDebugEnabled()) { 6 logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); 7 } 8 9 if (System.getSecurityManager() != null) { 10 try { 11 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { 12 public Object run() throws Exception { 13 //直接调用afterPropertiesSet 14 ((InitializingBean) bean).afterPropertiesSet(); 15 return null; 16 } 17 },getAccessControlContext()); 18 } catch (PrivilegedActionException pae) { 19 throw pae.getException(); 20 } 21 } 22 else { 23 //直接调用afterPropertiesSet 24 ((InitializingBean) bean).afterPropertiesSet(); 25 } 26 } 27 if (mbd != null) { 28 String initMethodName = mbd.getInitMethodName(); 29 //判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method 30 if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && 31 !mbd.isExternallyManagedInitMethod(initMethodName)) { 32 //进一步查看该方法的源码,可以发现init-method方法中指定的方法是通过反射实现 33 invokeCustomInitMethod(beanName, bean, mbd); 34 } 35 } 36 }
InitializingBean扩展

1 /** 2 * 构造方法、注解postConstruct,实现InitializingBean方法afterPropertiesSet,bean初始化init方法执行顺序。 3 * @author JustJavaIt 4 * @date 2022/9/10 15:030 5 */ 6 @Component 7 public class MyInitializingBean implements InitializingBean { 8 public MyInitializingBean() { 9 System.out.println("我是MyInitializingBean构造方法执行..."); 10 } 11 12 public void testInit(){ 13 System.out.println("我是init方法执行..."); 14 } 15 16 @Bean(initMethod = "testInit") 17 public MyInitializingBean test() { 18 return new MyInitializingBean(); 19 } 20 21 @Override 22 public void afterPropertiesSet() throws Exception { 23 System.out.println("我是afterPropertiesSet方法执行..."); 24 } 25 26 @PostConstruct 27 public void postConstruct() { 28 System.out.println("我是postConstruct方法执行..."); 29 } 30 31 }
运行结果如下:
我们可以看出执行顺序优先级:构造方法 > postConstruct >afterPropertiesSet > init方法。
感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章页面中给出作者和原文连接。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
2020-09-10 使用Lists.partition切分性能优化