前言
不知不覺畢業已經三年有餘,前面的時間一直忙於工作上的事情,最近稍微有點空閒時間,就準備梳理下自己的知識體系,發覺得自己的知識體系很是混亂和不足,正巧手中有一些書籍,藉此機會好好學習和梳理一番,也希望自己的一點小小記錄能分享給各位,帶給大家一些收穫。
一:Spring容器
Spring容器負責建立,管理物件,物件的整個生命週期都是由容器(container)負責的,下面是Spring中容器的介面的實現類
我們在開發中接觸和使用最多的就是其中的基於註解的配置類的AnnotationConfigWebApplicationContext上下文,和基於xml配置的XmlWebApplicationContext上下文,當然Spring容器的還要一個重要的功能DI(依賴注入)這個功能我將在下個章節學習二:Bean的生命週期
瞭解Bean的生命週期,有助於我們理解Bean在容器的運作過程,何時建立,何時呼叫,何時銷燬, spring對Bean例項化過程主要有以下幾個階段:
1:spring對bean進行例項化
2:spring將值和bean的引用注入到bean的對應屬性中
3:如果bean實現了BeanNameAware介面,Spring將bean的ID傳遞給setBeanName()方法
4:如果Bean實現了BeanFactoryAware介面,Spring將呼叫setBeanFactory()方法,將BeanFactory容器例項傳入
5:如果bean實現了ApplicationContextAware介面,Spring將呼叫setApplicationContext()方法,將bean所在的應用上下文的引用傳遞進來
6:如果bean實現了BeanPostProcessor介面,Spring將呼叫它的postProcessorBeforeInitialization()q前置處理方法
7:如果bean實現了InitializingBean介面,Spring將呼叫它們的afterPropertiesSet()方方法,類似的如果bean使用了init-method宣告瞭初始化方法,該方法也會被呼叫
8:如果bean實現了BeanPostProcessor介面,Spring將呼叫它們的postProcessorAfterInitialization()後置處理方法
9:此時bean已經準備就虛了,可以被應用程式使用了,它們將一直駐留在應用程式上下文中,直到該應用上下文被銷燬
10:如果bean實現了DisposableBean介面,Spring將呼叫它的destroy()介面方法,同樣,如果bean使用了destroy-method宣告瞭銷燬方法,該方法也會被呼叫
下面我們實際寫程式碼測試一下
首先我們定義一個實體類並且實現eanNameAware, BeanFactoryAware,ApplicationContextAware, InitializingBean, BeanPostProcessor, DisposableBean介面重寫父類的方法
package com.lly.springtest1.entity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* @ClassName GirlFriendEntity
* @Description bean實體類
* @Author lly
* @Date 2019/1/16
* @Version 1.0
**/
@Slf4j
public class GirlFriendEntity implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
private String name;
public GirlFriendEntity() {
log.info("呼叫GirlFriendEntity的無引數構造器方法");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
log.info("BeanFactoryAware呼叫setBeanFactory方法將BeanFactory例項傳入");
}
public String getName() {
return name;
}
public void setName(String name) {
log.info("對name屬性進行賦值");
this.name = name;
}
@Override
public void setBeanName(String s) {
log.info("BeanNameAware呼叫setBeanName方法,將bean的name注入");
}
@Override
public void destroy() throws Exception {
log.info("DisposableBean呼叫destroy方法");
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("InitializingBean呼叫afterPropertiesSet方法");
}
//自定義的初始化方法
@PostConstruct
public void myInit() {
log.info("呼叫自定義的init方法");
}
//自定義銷燬方法
@PreDestroy
public void myDestroy() {
log.info("呼叫自定義的destroy方法");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("呼叫ApplicationContext方法的setApplicationContext注入上下文");
}
}
複製程式碼
接著我們來定義個繼承BeanPostProcessor的類來觀察
package com.lly.springtest1.entity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @ClassName MyBeanPostProcessor
* @Description
* @Author lly
* @Date 2019/1/16
* @Version 1.0
**/
@Slf4j
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean.getClass() == GirlFriendEntity.class) {
log.info("BeanPostProcessor呼叫postProcessBeforeInitialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean.getClass() == GirlFriendEntity.class) {
log.info("BeanPostProcessor呼叫postProcessAfterInitialization");
}
return bean;
}
}
複製程式碼
然後啟動容器看看bean初始化的具體流程
package com.lly.springtest1.entity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName Test
* @Description
* @Author lly
* @Date 2019/1/16
* @Version 1.0
**/
@Configuration
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Test.class);
context.close();
}
@Bean
public MyBeanPostProcessor getBean() {
return new MyBeanPostProcessor();
}
@Bean
public GirlFriendEntity getGirl() {
GirlFriendEntity girl = new GirlFriendEntity();
girl.setName("穎寶");
return girl;
}
}
複製程式碼
列印結果如下
我們可以清晰看到bean的整個生命週期