Bean獲取和實例化
ApplicationContext與BeanFactory關係
ApplicationContext它是擴展BeanFactory接口。
BeanFactory它採取延遲加載的方案,只有真正在getBean時纔會實例化Bean
在開發中我們一般使用的是ApplicationContext,真正使用的是其實現類,
FileSystemXmlAppliCationContext 根據文件路徑獲取
ClassPathXmlApplicationContext 根據類路徑獲取
AppliCationContext它會在配置文件加載時,就會初始化Bean,並且ApplicationContext它提供不同的應用層的Context實現。例如在web開發中可以使用WebApplicationContext.
IOC獲取Bean實例化對象
- 在applicationContext.xml文件中配置bean
<bean id="userService" class="com.test.userServiceImpl"/>
- 創建一個AppliCationContext對象
ApplicationContext它是BeanFactory的一個子接口,我們在使用時使用的是AppliCationContext的實現類ClassPathXmlApplicationContext,獲取Spring配置上下文對象
//使用Spring的IOC容器;IOC本質是XML配置文件+反射+BeanFactory來實現
//Soring提供一個BeanFactory工廠統一管理Bean,使用其子接口ApplicationContext
//ClassPathXmlApplicationContext:在類路徑下根據參數文件名查找ApplicationContext.xml對象
ApplicationContext application=new ClassPathXmlApplicationContext("ApplicationContext");
UserService userService=(UserService)application.getBean("userService");
Bean的生命週期流程
- instantiate bean 構造方法實例化Bean對象
- populate properties 封裝屬性,di依賴注入
- 如果Bean實現BeanNameAware,執行setBeanName,也就是bean的id值
- 如果Bean實現BeanFactoryAwar或ApplicationContextAwar,需要設置工廠setBeanFactory或上下文對象setApplicationContext
- 如果存在類實現BeanPostProcessor(後處理Bean),執行postProcessBeforeInitialization,可以在初始化之前執行一些方法
- 如果Bean實現InitializingBean(初始化)接口,執行afterPropertiesSet方法(相當於自定義init-method),執行屬性設置之後的操作
- 調用自定義的< bean init-method=" " >初始化方法
- 如果存在類實現BeanPostProcessor(處理Bean),執行postProcessAfterInitialization,執行初始化之後的操作
- 執行業務處理(Bean可用)
- 如果Bean實現DisposableBean執行destroy
- 調用自定義的< bean destroy-method=’’ >銷燬方法
對於bean的生命週期方法:
第三步與第四步是讓Bean瞭解spring容器。
第五步與第八步 可以針對指定的Bean進行功能增強(在初始化前後執行),這時一般會使用動態代理.
第六步與第十步:通過實現指定的接口來完成init與destroy操作
但是在開發中一般不使用第6步與第10步,原因是我們可以使用第7步與第11步來完成。
第7步與第11步的初始化與銷燬操作它無耦合,推薦使用的。但是必須在配置文件中指定初始化與銷燬的方法
代碼實例:
在xml配置文件中配置相關的bean
<!-- 自定義bean -->
<bean id="testBean" name="bean1" class="com.dubbox.bean.TestBean" init-method="myInit" destroy-method="myDestroy">
<property name="beanStr" value="張三的歌"/>
<property name="beanInt" value="123"></property>
</bean>
<!-- 實現BeanPostProcessor接口的bean,spring ioc容器擴展 -->
<bean id="postProcessor" class="com.dubbox.bean.PostProcessor"></bean>
<!-- spring 註解掃描 -->
<context:component-scan base-package="com.dubbox"></context:component-scan>
Bean分別實現 BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean
/**
*
* @author 張江豐
* BeanNameAware:
* 實現setBeanName方法 設置Bean的id
* ApplicationContextAware/BeanFactoryBean:
* 實現setApplicationContext/setBeanFactory方法 設置ApplicationComtext上下文對象/BeanFactory
* BeanPostProcessor:
* 實現 postProcessBeforeInitialization 和 postProcessAfterInitialization 分別執行初始化執行之前和之後的方法
* InitializingBean:
* 實現afterPropertiesSet方法,進行Bean初始化,在屬性封裝之後執行
* DisposableBean:
* 實現destroy方法 銷燬執行
*
*/
@Scope(value = "singleton")
public class TestBean implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {
private String beanStr;
private Integer beanInt;
public String getName() {
return "zhangsan";
}
public String getBeanStr() {
return beanStr;
}
public void setBeanStr(String beanStr) {
this.beanStr = beanStr;
}
public Integer getBeanInt() {
return beanInt;
}
public void setBeanInt(Integer beanInt) {
this.beanInt = beanInt;
}
@Override
public void setBeanName(String name) {
// TODO Auto-generated method stub
System.out.println("調用setBeanName方法:" + name);
}
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
// TODO Auto-generated method stub
this.applicationContext = arg0;
// TestBean bean = (TestBean) applicationContext.getBean("testBean");
System.out.println("調用setApplicationContext方法,獲取Spring容器ApplicationContext對象:" + applicationContext);
}
@Override
public void destroy() throws Exception {
// TODO Auto-generated method stub
System.out.println("調用destroy方法,bean被銷燬了");
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
try {
System.out.println("調用afterPropertiesSet方法,bean初始化執行了");
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("bean初始化異常" + e.getMessage());
}
}
//@PostConstruct // 相當於在bean中配置了 init-method="myInit"
public void myInit() {
System.out.println("自定義init執行");
}
//@PreDestroy // 相當與在bean中配置了 destory-method="myDestroy"
public void myDestroy() {
System.out.println("自定義Destory執行");
}
}
自定義類實現BeanPostProcessor接口,分別實現postProcessBeforeInitialization和postProcessAfterInitialization方法,可以在bean初始化前後執行,需要在xml配置文件中配置,是springIOC容器的擴展
BeanPostProcessor接口也叫後置處理器,作用是在Bean對象在實例化和依賴注入完畢後,在顯示調用初始化方法的前後添加我們自己的邏輯。注意是Bean實例化完畢後及依賴注入完成後觸發的。
/**
* BeanPostProcessor是Spring IOC容器給我們提供的一個擴展接口
*
* @author 張江豐
*
*/
public class PostProcessor implements BeanPostProcessor {
@Override // 在bean初始化之前執行
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof TestBean) {
System.out.println("調用postProcessBeforeInitialization方法,在初始化init之前執行:" + beanName + "開始實例化");
}
// 從spring IOC容器中取出bean,使用後必須返回bean對象
return bean;
}
@Override // 在bean初始化之後執行
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof TestBean) {
System.out.println("調用postProcessAfterInitialization方法,在初始化init之後執行:" + beanName + "實例化完成");
}
// 從spring IOC容器中取出bean,使用後必須返回bean對象
return bean;
}
}
junit測試
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/applicationContext.xml" })
public class Test1 {
@Test
public void demo1() throws Exception {
ApplicationContext app = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
TestBean tb = (TestBean) app.getBean("testBean");
// TestBean tb = new TestBean();
System.out.println(tb.getBeanStr());
}
}
控制檯輸出內容
調用setBeanName方法:testBean
調用setApplicationContext方法,獲取Spring容器ApplicationContext對象:org.springframework.context.support.ClassPathXmlApplicationContext@63611043: startup date [Fri Feb 07 12:20:13 CST 2020]; root of context hierarchy
調用postProcessBeforeInitialization方法,在初始化init之前執行:testBean開始實例化
調用afterPropertiesSet方法,bean初始化執行了
自定義init執行
調用postProcessAfterInitialization方法,在初始化init之後執行:testBean實例化完成
張三的歌
調用destroy方法,bean被銷燬了
自定義Destory執行
由此可見控制檯輸出順序和springbean生命週期流程一致,首先執行實例化bean對象,設置對象屬性,檢查Aware相關接口,如果有類實現BeanPostProcessor接口,在bean初始化init前後執行擴展方法,bean可用狀態.