https://github.com/cuzz1/learn-demo/tree/master/demo-05-spring-annotation
1. 聲明周期@Bean指定初始化和銷毀方法
1 ) Bean的生命周期
Bean的創(chuàng)建、初始化和銷毀是由容器幫我們管理的
我們可以自定義初始化和銷毀方法,容器在進行到當前生命周期的時候來調(diào)用我買自定義的初始化和銷毀方法
構(gòu)造(對象創(chuàng)建)
? 單實例: 在容器啟動的時候創(chuàng)建
? 多實例: 在每次獲取的時候創(chuàng)建對象
2 ) 指定初始化方法
初始化:對象創(chuàng)建完成后,并賦值化,調(diào)用初始化方法
銷毀:單實例是在容器關(guān)閉的時候銷毀,多實例容器不會管理這個Bean,容器不會調(diào)用銷毀方法
編寫一個Car類
/**
* @Author: cuzz
* @Date: 2018/9/23 21:20
* @Description:
*/
public class Car {
public Car () {
System.out.println("car constructor...");
}
public void init() {
System.out.println("car...init...");
}
public void destroy() {
System.out.println("car...destroy...");
}
}
在xml中我們可以指定init-method和destroy-method方法,如
<bean id="car" class="com.cuzz.bean.Car" init-method="init" destroy-method="destroy"></bean>
使用注解我們可以
/**
* @Author: cuzz
* @Date: 2018/9/24 12:49
* @Description: 配置類
*/
@Configuration
public class MainConfigOfLifecycle {
@Bean(initMethod = "init", destroyMethod = "destroy")
public Car car() {
return new Car();
}
}
測試
/**
* @Author: cuzz
* @Date: 2018/9/24 13:00
* @Description:
*/
public class IOCTestLifeCycle {
@Test
public void test01() {
// 創(chuàng)建ioc容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfigOfLifecycle.class);
System.out.println("容器創(chuàng)建完成...");
// 關(guān)閉容器
System.out.println("--->開始關(guān)閉容器");
applicationContext.close();
System.out.println("--->已經(jīng)關(guān)閉容器");
}
}
可以看出先創(chuàng)建car,再調(diào)用init方法,在容器關(guān)閉時銷毀實例
car constructor...
car...init...
容器創(chuàng)建完成...
--->開始關(guān)閉容器
car...destroy...
--->已經(jīng)關(guān)閉容器
在配置數(shù)據(jù)源的時候,有很多屬性賦值,銷毀的時候要把連接給斷開
2. 生命周期InitializingBean和DisposableBean
1 ) InitializingBean
可以通過Bean實現(xiàn)InitializingBean來定義初始化邏輯,是設(shè)置好所有屬性會調(diào)用afterPropertiesSet()方法
public interface InitializingBean {
/**
* Invoked by a BeanFactory after it has set all bean properties supplied
* (and satisfied BeanFactoryAware and ApplicationContextAware).
* <p>This method allows the bean instance to perform initialization only
* possible when all bean properties have been set and to throw an
* exception in the event of misconfiguration.
* @throws Exception in the event of misconfiguration (such
* as failure to set an essential property) or if initialization fails.
*/
void afterPropertiesSet() throws Exception;
}
2)DisposableBean
可以通過Bean實現(xiàn)DisposableBean來定義銷毀邏輯,會調(diào)用destroy()方法
public interface DisposableBean {
/**
* Invoked by a BeanFactory on destruction of a singleton.
* @throws Exception in case of shutdown errors.
* Exceptions will get logged but not rethrown to allow
* other beans to release their resources too.
*/
void destroy() throws Exception;
}
3)例子
編寫一個Cat類
/**
* @Author: cuzz
* @Date: 2018/9/24 13:36
* @Description:
*/
public class Cat implements InitializingBean, DisposableBean{
public Cat() {
System.out.println("cat constructor...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("cat...init...");
}
@Override
public void destroy() throws Exception {
System.out.println("cat...destroy...");
}
}
測試
cat constructor...
cat...init...
容器創(chuàng)建完成...
--->開始關(guān)閉容器
cat...destroy...
--->已經(jīng)關(guān)閉容器
3. 生命周期@PostContruct和@PreDestroy注解
@PostContruct在Bean創(chuàng)建完成并且屬性賦值完成,來執(zhí)行初始化
@PreDestroy在容器銷毀Bean之前通知我們進行清理工作
編寫一個Dog類,并把他注入到配置類中
/**
* @Author: cuzz
* @Date: 2018/9/24 14:03
* @Description:
*/
public class Dog {
public Dog() {
System.out.println("dog constructor...");
}
@PostConstruct
public void postConstruct() {
System.out.println("post construct...");
}
@PreDestroy
public void preDestroy() {
System.out.println("pre destroy...");
}
}
測試結(jié)果
dog constructor...
post construct...
容器創(chuàng)建完成...
--->開始關(guān)閉容器
pre destroy...
--->已經(jīng)關(guān)閉容器
4. 生命周期BeanPostProscessor后置處理器
在Bean初始化前后做一些處理
public interface BeanPostProcessor {
// 在初始化之前工作
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// 在初始化之后工作
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
編寫一個MyBeanPostProcessor實現(xiàn)BeanPostProcessor接口
/**
* @Author: cuzz
* @Date: 2018/9/24 14:21
* @Description: 后置處理器,初始化前后進行處理工作
*/
public class MyBeanPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("--->postProcessBeforeInitialization..." + beanName +"==>" + bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("--->postProcessAfterInitialization..." + beanName +"==>" + bean);
return bean;
}
}
測試
--->postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerProcessor==>org.springframework.context.event.EventListenerMethodProcessor@1dc67c2
--->postProcessAfterInitialization...org.springframework.context.event.internalEventListenerProcessor==>org.springframework.context.event.EventListenerMethodProcessor@1dc67c2
--->postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerFactory==>org.springframework.context.event.DefaultEventListenerFactory@2bd765
--->postProcessAfterInitialization...org.springframework.context.event.internalEventListenerFactory==>org.springframework.context.event.DefaultEventListenerFactory@2bd765
cat constructor...
--->postProcessBeforeInitialization...cat==>com.cuzz.bean.Cat@1d3b207
cat...init...
--->postProcessAfterInitialization...cat==>com.cuzz.bean.Cat@1d3b207
容器創(chuàng)建完成...
--->開始關(guān)閉容器
cat...destroy...
--->已經(jīng)關(guān)閉容器
在實例創(chuàng)建之前后創(chuàng)建之后會被執(zhí)行
5. 生命周期BeanPostProcessor原理
通過debug到populateBean,先給屬性賦值在執(zhí)行initializeBean方法
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
initializeBean方法時,
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 執(zhí)行before方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
...
try {
// 執(zhí)行初始化
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (mbd == null || !mbd.isSynthetic()) {
// 執(zhí)行after方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
Spring底層對BeanPostProcessor的使用:
Bean賦值、注入其他組件、@Autowired、生命周期注解功能、@Async等等都使用到了BeanPostProcessor這個接口的實現(xiàn)類,很重要