spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用。如下:
import org.springframework.beans.factory.InitializingBean; public class TestInitializingBean implements InitializingBean{ @Override public void afterPropertiesSet() throws Exception { System.out.println("ceshi InitializingBean"); } public void testInit(){ System.out.println("ceshi init-method"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="testInitializingBean" class="com.TestInitializingBean" init-method="testInit"></bean> </beans>
疑问:如果bean实现了InitializingBean接口同时在配置文件中又制定了init-method方法,那么会先调用那个方法呢?查源码
AbstractAutowireCapableBeanFactory.java 的invokeInitMethods方法源码如下:
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable { //判断bean是否实现了InitializingBean boolean isInitializingBean = (bean instanceof InitializingBean); //如果实现了InitializingBean并且.... if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } //调用afterPropertiesSet()方法 ((InitializingBean) bean).afterPropertiesSet(); } //判断是否指定了init-method方法,如果制定了再调用init-method方法 String initMethodName = (mbd != null ? mbd.getInitMethodName() : null); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //init-method方法是用反射实现的 invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod()); } }
实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖 如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。