先看一個Spring中Bean的實例化過程:

1.配置文件中指定Bean的init-method參數
<bean class="com.jts.service.UserService" init-method="init"></bean>
缺點:注解方式實例化Bean時無法使用
2.Bean實現InitializingBean接口(推薦,Spring源碼和框架搭建中大量使用)
InitializingBean接口只有一個方法afterPropertiesSet,實例化Bean時會調用該方法
注意:
1.如果兩種方式同時存在,會先執行afterPropertiesSet方法后執行init-method指定的方法,原因見Spring源碼AbstractAutowireCapableBeanFactory類invokeInitMethods方法
2.實現接口為直接調用afterPropertiesSet方法,配置init-method為反射調用,所有實現接口效率較高
/** * Give a bean a chance to react now all its properties are set, * and a chance to know about its owning bean factory (this object). * This means checking whether the bean implements InitializingBean or defines * a custom init method, and invoking the necessary callback(s) if it does. * @param beanName the bean name in the factory (for debugging purposes) * @param bean the new bean instance we may need to initialize * @param mbd the merged bean definition that the bean was created with * (can also be {@code null}, if given an existing bean instance) * @throws Throwable if thrown by init methods or by the invocation process * @see #invokeCustomInitMethod */ protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } }
/** * Invoke the specified custom init method on the given bean. * Called by invokeInitMethods. * <p>Can be overridden in subclasses for custom resolution of init * methods with arguments. * @see #invokeInitMethods */ protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { String initMethodName = mbd.getInitMethodName(); final Method initMethod = (mbd.isNonPublicAccessAllowed() ? BeanUtils.findMethod(bean.getClass(), initMethodName) : ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName)); if (initMethod == null) { if (mbd.isEnforceInitMethod()) { throw new BeanDefinitionValidationException("Couldn't find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'"); } else { if (logger.isDebugEnabled()) { logger.debug("No default init method named '" + initMethodName + "' found on bean with name '" + beanName + "'"); } // Ignore non-existent default lifecycle methods. return; } } if (logger.isDebugEnabled()) { logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ReflectionUtils.makeAccessible(initMethod); return null; } }); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { initMethod.invoke(bean); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { InvocationTargetException ex = (InvocationTargetException) pae.getException(); throw ex.getTargetException(); } } else { try { ReflectionUtils.makeAccessible(initMethod); initMethod.invoke(bean); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
