手寫Spring框架-壹
背景
最近工作比較輕松,于是趁著手里沒有活,就打算自己寫一個簡單的Spring框架,因為之前背Spring的八股的時候老是背了就忘。
--本來前面寫的好好的,也能勉強理解,但是到了第七章寫應用上下文時,一下子來了十多個接口和抽象類,直接就蒙了,于是打算畫圖幫助理解,并且寫博客記錄,防止以后又忘了。。
參考
小傅哥:https://bugstack.cn/md/spring/develop-spring/2021-05-16-第1章:開篇介紹,手寫Spring能給你帶來什么?.html
因為前面第七章前面并不難,所以直接從第七章開始。
首先介紹一下Bean的生命周期:
1. 容器啟動階段
加載配置(XML、注解、JavaConfig)
解析成 BeanDefinition(class、scope、依賴等元信息)
注冊到 BeanDefinitionRegistry
2. BeanFactoryPostProcessor 階段
觸發時機:在任何 Bean 實例化之前
作用:修改 BeanDefinition 的元信息
典型用途:占位符替換 ${}、動態修改屬性值等
注意:此時 Bean 還沒有被創建。
3. Bean 實例化階段
Spring 調用構造方法 / 工廠方法,new 出對象。
此時只是一個“空殼對象”,還沒有屬性。
4. 屬性填充(依賴注入)
Spring 根據 BeanDefinition 里的信息,進行 依賴注入:
XML 里
構造器 / Setter 注入
時機:實例化之后,初始化之前
5. BeanPostProcessor 前置處理
調用 postProcessBeforeInitialization(bean, beanName)
在 Bean 初始化方法之前執行
6. 初始化方法
如果實現了 InitializingBean,執行 afterPropertiesSet()
7. BeanPostProcessor 后置處理
調用 postProcessAfterInitialization(bean, beanName)
8. Bean 就緒
現在 Bean 已經完全可用了,交給容器管理。
正文
本章的目標是實現滿足于在 Bean 對象從容器啟動到Bean可用的過程中執行用戶的自定義操作,但是如果只是添加這兩個接口,不做任何包裝,那么對于使用者來說還是非常麻煩的。我們希望于開發 Spring 的上下文操作類,把相應的 XML 加載 、注冊、實例化以及新增的修改和擴展都融合進去,讓 Spring 可以自動掃描到我們的新增服務,便于用戶使用。

提供給用戶的擴展接口
首先是BeanFactoryPostProcessor接口,該接口是spring提供給用戶使用的接口,用戶實現該接口就可以在Bean實例化之前使用BeanFactory對Bean的注冊信息進行操作。
注意:此時 Bean 還沒被創建。
public interface BeanFactoryPostProcessor {
/**
* 在所有的 BeanDefinition 加載完成后,實例化 Bean 對象之前,提供修改 BeanDefinition 屬性的機制
*
* @param beanFactory
* @throws BeansException
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
然后是實現BeanPostProcessor接口,該接口是spring提供給用戶使用的接口,用戶通過實現該接口,就可以在Bean初始化前后對Bean進行操作。
public interface BeanPostProcessor {
/**
* 在 Bean 對象執行初始化方法之前,執行此方法
*
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* 在 Bean 對象執行初始化方法之后,執行此方法
*
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
Spring內部使用的接口
上面講的是Spring提供給用戶使用的接口,而spring內部也得有相關的定義,才能支持這種擴展
ListableBeanFactory接口
該接口的作用是可以獲取IOC容器里的多個Bean,是對BeanFactory的擴展,BeanFactory一次只能獲取一個Bean
public interface ListableBeanFactory extends BeanFactory{
/**
* 按照類型返回 Bean 實例
* @param type
* @param <T>
* @return
* @throws BeansException
*/
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
/**
* Return the names of all beans defined in this registry.
*
* 返回注冊表中所有的Bean名稱
*/
String[] getBeanDefinitionNames();
}
HierarchicalBeanFactory接口
這是一個標記性接口,定義了spring容器分層的概念
public interface HierarchicalBeanFactory extends BeanFactory {
}
AutowireCapableBeanFactory接口
這個接口很容易與前面的BeanPostFactory接口混淆,這個接口是Spring內部使用的!!!
繼承BeanFactory接口是需要獲得getBean的能力,它本身提供了兩個方法,用于在Bean初始化前后
public interface AutowireCapableBeanFactory extends BeanFactory {
/**
* 執行 BeanPostProcessors 接口實現類的 postProcessBeforeInitialization 方法
* 在Bean初始化之前執行一些操作-BeforeInitialization
*
* @param existingBean
* @param beanName
* @return
* @throws BeansException
*/
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
/**
* 執行 BeanPostProcessors 接口實現類的 postProcessorsAfterInitialization 方法
* 在Bean初始化之后執行一些操作-AfterInitialization
*
* @param existingBean
* @param beanName
* @return
* @throws BeansException
*/
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
}
ConfigurableBeanFactory接口
繼承HierarchicalBeanFactory代表支持容器分層的能力
繼承SingletonBeanRegistry代表有獲取單例Bean的能力
它的功能是在BeanFactory基礎上,一個支持父子容器、單例緩存并且可以有生命周期擴展(BeanPostProcessor-Bean初始化前后擴展處理的能力)
并且具有保存和管理 BeanPostProcessor 列表的能力,定義了addBeanPostProcessor()方法
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
/**
* 兩種作用域
*/
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
}
ConfigurableListableBeanFactory接口
這個接口非常重要,它繼承了ListableBeanFactory(支持一次獲取多個Bean的能力)、AutowireCapableBeanFactory(支持自動注入能力-創建和裝配Bean)、
ConfigurableBeanFactory(支持作用域、配置、Bean初始化前后擴展的能力)
這代表了這個接口能夠完整實現IOC容器的所有職責,實現了它就代表了是一個完整Spring容器!!!
public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
BeanDefinition getBeanDefinition(String beanName) throws BeansException;
void preInstantiateSingletons() throws BeansException;
}
到了這里,Spring內部管理Bean實例的接口就創建好了,接下來創建上下文相關接口
ApplicationContext是對外的接口,給用戶使用的,所以得繼承ListableBeanFactory來獲得對Bean的查詢能力,方便用戶獲取Bean。
問題:為什么不繼承其他繼承了BeanFactory的接口,比如ConfigurableBeanFactory,它也有這些功能?
解答:還是上面那句話,ApplicationContext是給用戶使用的,而ConfigurableBeanFactory是給容器內部使用的
ApplicationContext接口
public interface ApplicationContext extends ListableBeanFactory {
}
ConfigurableApplicationContext接口
refresh()是spring容器的核心啟動方法
這也是給spring內部容器使用的,所以單獨創建了它,而不是在ApplicationContext里定義refresh()方法
public interface ConfigurableApplicationContext extends ApplicationContext{
/**
* 刷新容器
* @throws BeansException
*/
void refresh() throws BeansException;
}
AbstractApplicationContext抽象類
該抽象類用模板方法模式實現了refresh()方法邏輯
并且繼承了DefaultResourceLoader來獲得加載資源的能力,因為refresh()需要解析xml文件加載Bean
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException {
// 1. 創建 BeanFactory,并加載 BeanDefinition
refreshBeanFactory();
// 2. 獲取 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3. 在 Bean 實例化之前,執行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)
// 真正執行了
invokeBeanFactoryPostProcessors(beanFactory);
// 4. BeanPostProcessor 需要提前于其他 Bean 對象實例化之前執行注冊操作
// 只是注冊,加入到執行鏈中,并沒有執行
registerBeanPostProcessors(beanFactory);
// 5. 提前實例化單例Bean對象
beanFactory.preInstantiateSingletons();
}
/**
* 獲取所有實現了BeanPostProcessor的Bean,將它加到BeanPostProcessor執行鏈,getBeansOfType()返回的就是beanDefinitionMap的遍歷順序,也就是注冊順序
* 即BeanPostProcessor執行鏈里執行的順序是它的注冊順序
* 如果需要改變執行的優先級,可以實現 PriorityOrdered 或 Ordered 接口
* @param beanFactory
*/
private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
beanFactory.addBeanPostProcessor(beanPostProcessor);
}
}
/**
* 直接執行了BeanFactoryProcessor
* @param beanFactory
*/
private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
for (BeanFactoryPostProcessor beanFactoryPostProcessor:beanFactoryPostProcessorMap.values()){
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
}
}
/**
* 門面+委托模式的應用,在這里再次實現getBeansOfType只是因為ApplicationContext是對用戶使用的,
* 這里再次實現只是提供一個門面,但是真正實現還是委托給DefaultListableBeanFactory去做
* @param type
* @return
* @param <T>
* @throws BeansException
*/
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return getBeanFactory().getBeansOfType(type);
}
@Override
public String[] getBeanDefinitionNames() {
return getBeanFactory().getBeanDefinitionNames();
}
@Override
public Object getBean(String beanName) {
return getBeanFactory().getBean(beanName);
}
@Override
public Object getBean(String beanName, Object... args) {
return getBeanFactory().getBean(beanName, args);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return getBeanFactory().getBean(name, requiredType);
}
protected abstract void refreshBeanFactory() throws BeansException;
protected abstract ConfigurableListableBeanFactory getBeanFactory();
}
AbstractRefreshableApplicationContext抽象類
實現了父類AbstractApplicationContext的refreshBeanFactory()和getBeanFactory()方法
分擔了父類AbstractApplicationContext的解析xml文件并創建beanFactory的職責
自己實現了創建beanFactory的功能
并且定義了抽象方法loadBeanDefinitions將解析xml文件的職責下發給子類
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext{
private DefaultListableBeanFactory beanFactory;
@Override
protected void refreshBeanFactory() throws BeansException {
DefaultListableBeanFactory beanFactory = createBeanFactory();
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);
private DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory();
}
@Override
protected ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
}
AbstractXmlApplicationContext抽象類
負責解析配置文件并注冊Bean的功能
定義抽象方法getConfigLocations()將獲取配置文件的職責下發
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext{
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(this, beanFactory);
String[] configLocations = getConfigLocations();
if(null != configLocations && configLocations.length > 0) {
xmlBeanDefinitionReader.loadBeanDefinitions(configLocations);
}
}
protected abstract String[] getConfigLocations();
}
ClassPathXmlApplicationContext抽象類
負責獲取xml文件
ClassPathXmlApplicationContext是這條繼承鏈的終點,也是spring容器啟動的起點
通過調用refresh()來啟動容器
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
private String[] configLocations;
public ClassPathXmlApplicationContext() {}
public ClassPathXmlApplicationContext(String configLocation) {
this(new String[]{configLocation});
}
public ClassPathXmlApplicationContext(String[] configLocations) {
this.configLocations = configLocations;
//開啟容器啟動流程
refresh();
}
@Override
protected String[] getConfigLocations() {
return configLocations;
}
}
spring容器內部在哪擴展?
BeanFactoryPostProcessor在AbstractApplicationContext抽象類的refresh()方法里直接執行,
而BeanPostProcessor只是在這里把所有實現了BeanPostProcessor的接口加入到BeanPostProcessor執行鏈。
而真正執行BeanPostProcessor是在Bean實例化之后,初始化前后,也就是AbstractAutowireCapableBeanFactory的createBean方法初始化前后
目前第七章的架構圖


浙公網安備 33010602011771號