1.Bean的作用域
- singleton:單例Bean只在容器中存在一個實例,在Spring內部通過HashMap來維護單例bean的緩存
- prototype:每次索取bean時都會創(chuàng)建一個全新的Bean
- request:每次請求都會創(chuàng)建一個全新Bean狼忱,該類型作用于Web類型的Spring容器
- session:每個會話創(chuàng)建一個全新Bean膨疏,該類型作用于Web類型的Spring容器
- globalSession:類似于session作用域,只是其用于portlet環(huán)境的web應用钻弄。如果在非portlet環(huán)境將視為session作用域
- 總結:以上就是spring中bean的作用域佃却,其中singleton,prototype屬于Spring bean的基本作作用域窘俺,request饲帅,session,globalSession屬于web應用環(huán)境的作用域瘤泪,必須有web應用環(huán)境的支持
2.Bean的生命周期
20180905094458523.png
- IoC容器啟動
- 實例化bean
- 如果Bean實現了BeanNameAware接口灶泵,則調用setBeanName(String name)返回beanName,該方法不是設置beanName对途,而只是讓Bean獲取自己在BeanFactory配置中的名字
- 如果Bean實現BeanFactoryAware接口赦邻,會回調該接口的setBeanFactory(BeanFactory beanFactory)方法,傳入該Bean的BeanFactory实檀,這樣該Bean就獲得了自己所在的BeanFactory
- 如果Bean實現了ApplicationContextAware接口惶洲,則調用該接口的setApplicationContext(ApplicationContext applicationContext)方法,設置applicationContext
- 如果有Bean實現了BeanPostProcessor接口劲妙,則調用該接口的postProcessBeforeInitialzation(Object bean湃鹊,String beanName)方法,將此BeanPostProcessor應用于給定的新bean實例
- 如果Bean實現了InitializingBean接口镣奋,則會回調該接口的afterPropertiesSet()方法
- 如果Bean配置了init-method方法币呵,則會執(zhí)行init-method配置的方法
- 如果Bean實現了BeanPostProcessor接口,則會回調該接口的postProcessAfterInitialization(Object bean,String beanName)方法
- 到此為止余赢,spring中的bean已經可以使用了芯义,這里又涉及到了bean的作用域問題,對于singleton類型的bean妻柒,Spring會將其緩存;對于prototype類型的bean扛拨,不緩存,每次都創(chuàng)建新的bean的實例
- 容器關举塔,如果Bean實現了DisposableBean接口绑警,則會回調該接口的destroy()方法銷毀bean,
- 如果用戶配置了定destroy-method央渣,則調用自定義方法銷毀bean
來看實際的例子:
- bean
package com.lyc.cn.v2.day01.lifecycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class LifeCycleBean implements
BeanNameAware,
BeanFactoryAware,
ApplicationContextAware,
InitializingBean,
DisposableBean {
// 姓名
private String name;
// 年齡
private int age;
@Override
public void setBeanName(String name) {
System.out.println("01-->BeanNameAware接口被調用了, 獲取到的beanName:" + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("02-->BeanFactoryAware接口被調用了");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("03-->ApplicationContextAware接口被調用了");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("05-->InitializingBean接口被調用了");
}
public void myInit() {
System.out.println("06-->myInit方法被調用了");
}
@Override
public void destroy() throws Exception {
System.out.println("09-->DisposableBean接口被調用了");
}
public void myDestroy() {
System.out.println("10-->自定義destroy-method方法被調動了");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "MyLifeCycleBean{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
package com.lyc.cn.v2.day01.lifecycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class LifeCycleBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof LifeCycleBean) {
System.out.println("04-->調用postProcessBeforeInitialization方法, 獲取到的beanName: " + beanName);
((LifeCycleBean) bean).setName("李四");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof LifeCycleBean) {
System.out.println("07-->調用postProcessAfterInitialization, 獲取到的beanName: " + beanName);
((LifeCycleBean) bean).setAge(30);
}
return bean;
}
}
- xml
<!-- ====================生命周期==================== -->
<!--注意:這里配置的name是張三计盒,age是25,我們會通過beanPostProcessor來修改nage和age -->
<bean id="myLifeCycleBean" class="com.lyc.cn.v2.day01.lifecycle.LifeCycleBean"
destroy-method="myDestroy"
init-method="myInit">
<property name="name" value="張三"/>
<property name="age" value="25"/>
</bean>
<bean id="myBeanPostProcessor" class="com.lyc.cn.v2.day01.lifecycle.LifeCycleBeanPostProcessor"/>
- 測試
@Test
public void test13() {
// 生命周期測試
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("v2/day01.xml");
LifeCycleBean myLifeCycleBean = applicationContext.getBean("myLifeCycleBean", LifeCycleBean.class);
System.out.println("08-->bean可以被使用了, beanInfo: " + myLifeCycleBean.toString());
((ClassPathXmlApplicationContext) applicationContext).destroy();
}
- 結果
========測試方法開始=======
01-->BeanNameAware接口被調用了, 獲取到的beanName:myLifeCycleBean
02-->BeanFactoryAware接口被調用了
03-->ApplicationContextAware接口被調用了
04-->調用postProcessBeforeInitialization方法, 獲取到的beanName: myLifeCycleBean
05-->InitializingBean接口被調用了
06-->myInit方法被調用了
07-->調用postProcessAfterInitialization, 獲取到的beanName: myLifeCycleBean
08-->bean可以被使用了, beanInfo: MyLifeCycleBean{name='李四', age=30}
09-->DisposableBean接口被調用了
10-->自定義destroy-method方法被調動了
========測試方法結束=======