InitializingBean
spring的InitializingBean為bean提供了定義初始化方法的方式。InitializingBean是一個接口,只包含一個方法:afterPropertiesSet():
public interface InitializingBean
public abstract void afterPropertiesSet()
throws Exception;
}
用法示例:
Bean實現:
import org.springframework.beans.factory.InitializingBean;
publicclass LifeCycleBean implements InitializingBean{
void afterPropertiesSet() throws Exception {
System.out.println("LifeCycleBean initializing...");
}
}
在xml配置文件中並不需要對bean進行特殊的配置:
<beans>
<bean name =
"lifeBean" class ="com.spring.LifeCycleBean"></beans >
編寫測試程序進行測試:
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class LifeCycleTest {
public static void main(String[] args) {
XmlBeanFactory factory= new XmlBeanFactory( new ClassPathResource("com/spring/applicationcontext.xml"));
factory.getBean("lifeBean");
}
}
運行之后,我們可以看到下面的結果:LifeCycleBean initializing...。說明bean的afterPropertiesSet方法被spring調用了。
spring在裝配完一個bean的所有合作者之后,會檢查這個bean是否實現了InitializingBean接口,如果實現就調用該bean的afterPropertiesSet方法。
init-method
Spring雖然可以通過InitializingBean完成bean初始化后對這個bean的回調,但是這種方式要求bean實現InitializingBean接口。一但bean實現了InitializingBean接口,那么這個bean的代碼就和Spring耦合到一起了。通常情況下我不鼓勵bean直接實現InitializingBean,可以使用Spring提供的init-method的功能來執行一個bean子定義的初始化方法。
bean實現:
package com.spring;
public class LifeCycleBean{
publicvoid init(){
System. out .println("LifeCycleBean.init...");
}
}
在Spring配置文件中配置這個bean:
<bean name ="lifeBean" class ="research.spring.beanfactory.ch4.LifeCycleBean" init-method ="init"></bean>
</beans>
當spring實例化lifeBean時,你會看到控制台上打印出LifeCycleBean.init...
Spring要求init-method是一個無參的方法,如果init-method指定的方法中有參數,那么Spring將會拋出java.lang.NoSuchMethodException。init-method指定的方法可以是public、protected以及private的,並且方法也可以是final的。另外,init-method指定的方法可以是聲明為拋出異常的,就像這樣:
final protected void init() throws Exception{
System.out.println(
"init method...");
throw new Exception("init exception");
}
通過分析上面的源代碼我們可以看到,init-method是通過反射執行的,而afterPropertiesSet是直接執行的。所以afterPropertiesSet的執行效率要比init-method高,不過init-method消除了bean對Spring依賴。在實際使用時我推薦使用init-method。另外,需要注意的是Spring總是先處理bean定義的InitializingBean,然后才處理init-method。如果在Spirng處理InitializingBean時出錯,那么Spring將直接拋出異常,不會再繼續處理init-method。
如果一個bean被定義為非單例的,那么afterPropertiesSet和init-method在bean的每一個實例被創建時都會執行。單例 bean的afterPropertiesSet和init-method只在bean第一次被實例時調用一次。大多數情況下 afterPropertiesSet和init-method都應用在單例的bean上。
可以借助這個InitializingBean方法來完成一些需要在bean初始化時完成的工作。
示例場景:
一個bean在初始化時需要讀取項目目錄中某個文件夾下的配置文件。
bean配置:
<bean id=
"testServiceConfig" class="com.lmb.client.TestlServiceConfigImpl">
<property name=
"folderName" value="test_config" />
調用代碼:
public class TestServiceConfigImpl implements InitializingBean {
private String folderName;
@Override
public void afterPropertiesSet()throws Exception{
folderName = folderName != null ? folderName : "test_config";
reload(folderName);
}
public void reload(String fileName) throws Exception {
fileName = fileName.startsWith("/") ? fileName.substring(1) : fileName;
File file = ResourceUtils.getFile("classpath:" + fileName);
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File configFile : files) {
}
}
}