Spring中的初始化InitializingBean介面和DisposableBean介面
最近在看關於redis整合的程式碼的時候,配置jedis的擴充套件操作RedisTemplate類,其中有屬性設定jedis連線,忍不住好奇,看了看RedisTemplate的實現。發現RedisTemplate類繼承了RedisAccessor,而RedisAccessor提供了redis庫的連線方法,還實現了InitializingBean。InitializingBean有什麼用?為什麼要實現這個介面?
度娘了一下,原來InitializingBean提供了afterPropertiesSet方法,凡是繼承該介面的類,在初始化bean的時候會執行該方法。也就是說只有類繼承InitializingBean,我們就可以在afterPropertiesSet方法中新增一下自己的操作,一旦bean初始化,就會自動執行afterPropertiesSet方法。比如,判斷redis連線是不是能取到。
實現InitializingBean介面與在配置檔案中指定init-method有什麼不同?
檢視spring的載入bean的原始碼類(AbstractAutowireCapableBeanFactory)可看出,AbstractAutowireCapableBeanFactory類中的invokeInitMethods實現
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { <span style="white-space:pre"> </span>//判斷該bean是否實現了實現了InitializingBean介面,如果實現了InitializingBean介面,呼叫bean的afterPropertiesSet方法 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>() { public Object run() throws Exception { //直接呼叫afterPropertiesSet ((InitializingBean) bean).afterPropertiesSet(); return null; } },getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //直接呼叫afterPropertiesSet ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); //判斷是否指定了init-method方法,如果指定了init-method方法,則再呼叫制定的init-method if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //進一步檢視該方法的原始碼,可以發現init-method方法中指定的方法是通過反射實現 invokeCustomInitMethod(beanName, bean, mbd); } } }
總結:
1、spring提供了兩種初始化bean的方式,實現InitializingBean介面中的afterPropertiesSet方法,或者在配置檔案中設定init-method。
2、實現InitializingBean介面是直接呼叫afterPropertiesSet方法,而init-method是通過反射來實現,效率較低,但是init-method方式消除了對spring的依賴。
3、InitializingBean介面實現先於init-method方法,如果呼叫afterPropertiesSet方法時出錯,則不呼叫init-method指定的方法。
同樣,對於DisposableBean介面,它也只提供一個方法destroy()。如果實現了DisposebleBean介面,那麼Spring將自動呼叫bean中的