大家好,又見面了,我是你們的朋友全棧君。
前言
在 spring 中,任何實作了
BeanFactory
接口的類都可以視為容器,它是
IOC
功能實作的核心,用于完成類執行個體從加載到銷毀的整個生命周期的控制,這些被 spring 所管理的執行個體統稱為 bean。
根據抽象層級的不同,容器又分為
BeanFactory
的直接實作,與基于
BeanFactory
的擴充實作
ApplicationContext
,後者在前者的基礎繼承了
ResourceLoader
和
EnvironmentCapable
接口,因而具備從某類運作環境的資源中直接加載 bean 的能力。
ApplicationContext
最常用的兩個實作
ClassPathXmlApplicationContext
和
AnnotationConfigApplicationContext
,前者用于從項目路徑下根據
xml
檔案加載 bean,而後者通過掃描類注解完成 bean 的加載。這兩者
ApplicationContext
實際上就對應了我們所熟悉的兩類配置方式,前者就是傳統的 xml 配置,後者則是通過
@Component
與
@Bean
等注解對 bean 進行配置。
本文将基于 spring 源碼
5.2.x
分支,基于
BeanFactory
與
ApplicationContext
兩大接口,介紹 spring 的兩類容器的結構體系。
一、BeanFactory 接口體系
總覽
BeanFactory
體系,按照接口的抽象層次,大體可以分層四層:
- 第一層:
;BeanFactory
- 第二層:
,HierarchicalBeanFactory
,ListableBeanFactory
;AutowireCapableBeanFactory
- 第三層:
,此外還有一個關聯性較強ConfigurableBeanFactory
;SingletonBeanRegistry
- 第四層:
;ConfigurableListableBeanFactory
1、BeanFactory
BeanFactory
是整個容器體系最頂層的接口,它的内容如下:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
// 擷取bean相關的方法
Object getBean(String name) throws BeansException;
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
// 容器 bean 屬性的一些判斷
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
// 擷取 bean 在容器中的一些屬性
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
複制
我們可以直接從
BeanFactory
提供的方法看出,
BeanFactory
定義了容器的一些基本能力:
- 容器可以根據名稱、類型、構造函數這三個要素,單獨或兩兩組合的的獲得一個 bean;
- 容器擷取的 bean 可以是單例多種多例的;
- 容器中的 bean 可以擁有多個名稱;
2、分層工廠,批量工廠,自動裝配工廠
BeanFactory
存在兩個子接口
HierarchicalBeanFactory
和
ListableBeanFactory
,它們進一步的擴充了容器的能力。
分層工廠 HierarchicalBeanFactory
HierarchicalBeanFactory
接口用于表示一個多集嵌套的
BeanFactory
:
public interface HierarchicalBeanFactory extends BeanFactory {
// 擷取父工廠
BeanFactory getParentBeanFactory();
// 目前工廠是否存在與名稱對應的 bean
boolean containsLocalBean(String name);
}
複制
批量工廠 ListableBeanFactory
ListableBeanFactory
接口定義了容器根據類型、名稱或類上的注解批量的擷取 bean 或 bean 名稱的能力:
public interface ListableBeanFactory extends BeanFactory {
// 容器中是否存在 bean
boolean containsBeanDefinition(String beanName);
// 容器中定義了多少 bean
int getBeanDefinitionCount();
// 擷取容器中所有定義了的 bean 名稱
String[] getBeanDefinitionNames();
// 根據類型批量擷取 bean
String[] getBeanNamesForType(ResolvableType type);
String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);
String[] getBeanNamesForType(@Nullable Class<?> type);
String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;
// 根據類上的注解擷取 bean
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException;
}
複制
根據注釋,當一個類同時實作了
HierarchicalBeanFactory
和
ListableBeanFactory
接口時,
ListableBeanFactory
中的方法是不會考慮到父工廠的,也就是說,spring 中的
ListableBeanFactory
接口表示的能力隻針對目前實作它的類。
自動裝配工廠 AutowireCapableBeanFactory
AutowireCapableBeanFactory
如同他的名稱一樣,用于為容器關聯的 bean 提供自動裝配功能:
public interface AutowireCapableBeanFactory extends BeanFactory {
// 自動裝配方式
int AUTOWIRE_NO = 0; // 不自動裝配
int AUTOWIRE_BY_NAME = 1; // 根據bean名稱自動裝配
int AUTOWIRE_BY_TYPE = 2; // 根據bean類型自動裝配
int AUTOWIRE_CONSTRUCTOR = 3; // 根據bean的構造方法自動裝配
int AUTOWIRE_AUTODETECT = 4; // 根據反射資訊自動選擇合适的方式自動裝配,spring3 以後不再推薦該方式
String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
// bean的建立與裝配相關的方法
<T> T createBean(Class<T> beanClass) throws BeansException;
void autowireBean(Object existingBean) throws BeansException;
Object configureBean(Object existingBean, String beanName) throws BeansException;
// bean 聲明周期相關的方法
Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException;
void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;
Object initializeBean(Object existingBean, String beanName) throws BeansException;
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
void destroyBean(Object existingBean);
// 擷取 bean 依賴的相關方法
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
}
複制
比較值得注意的是,通過
AutowireCapableBeanFactory
定義的 API 不難看出,隻要能獲得對應的執行個體,我們是可以手動的對非 spring 托管的 bean 進行依賴注入的。
3、分層配置工廠
BeanFactory
的三級接口為
ConfigurableBeanFactory
,它實作了
HierarchicalBeanFactory
和
SingletonBeanRegistry
接口。
從字面上了解,它是一個可配置的
BeanFactory
,它不僅支援
BeanFactory
分層,還支援以單例的方式操作 bean。它是整個
BeanFactory
體系中最重要的一環,通過這個接口,spring 通過該接口規定了一個
BeanFactory
應該具備以及可以從中擷取哪些可配置的元件與參數。
這裡我們先了解一下
SingletonBeanRegistry
接口,這個接口定義了容器根據名稱注冊或擷取 bean 單例的能力:
public interface SingletonBeanRegistry {
void registerSingleton(String beanName, Object singletonObject);
Object getSingleton(String beanName);
boolean containsSingleton(String beanName);
String[] getSingletonNames();
int getSingletonCount();
Object getSingletonMutex();
}
複制
然後回到
ConfigurableBeanFactory
,它在
HierarchicalBeanFactory
的基礎上補充了大量的方法:
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
String SCOPE_SINGLETON = "singleton"; // 單例
String SCOPE_PROTOTYPE = "prototype"; // 多例
// 配置父工廠
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
// 配置類加載器
void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);
ClassLoader getBeanClassLoader();
void setTempClassLoader(@Nullable ClassLoader tempClassLoader);
ClassLoader getTempClassLoader();
// 配置bean元資訊緩存
void setCacheBeanMetadata(boolean cacheBeanMetadata);
boolean isCacheBeanMetadata();
// 配置bean配置的表達式解析器,用于提供@Value值注冊等功能
void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);
BeanExpressionResolver getBeanExpressionResolver();
// 配置類型轉換器
void setConversionService(@Nullable ConversionService conversionService);
ConversionService getConversionService();
void setTypeConverter(TypeConverter typeConverter);
TypeConverter getTypeConverter();
// 配置屬性系統資料庫
void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);
void copyRegisteredEditorsTo(PropertyEditorRegistry registry);
// 配置字元串解析器,用于提供解析xml中的bean屬性的表達式等功能
void addEmbeddedValueResolver(StringValueResolver valueResolver);
boolean hasEmbeddedValueResolver();
String resolveEmbeddedValue(String value);
// 配置bean的後置處理器BeanPostProcessor
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
int getBeanPostProcessorCount();
// 配置bean的作用域,接口中已經預設提供了單例或多例的scopeName
void registerScope(String scopeName, Scope scope);
String[] getRegisteredScopeNames();
Scope getRegisteredScope(String scopeName);
// 配置通路控制
AccessControlContext getAccessControlContext();
// 從其他的工廠複制配置
void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);
// 給指定的bean注冊别名
void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;
void resolveAliases(StringValueResolver valueResolver);
// 合并bean的定義資訊
BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 是否是工廠bean
boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;
// 設定bean的建立狀态,管理bean的依賴與被依賴關系,用于處理循環依賴等問題
void setCurrentlyInCreation(String beanName, boolean inCreation);
boolean isCurrentlyInCreation(String beanName);
void registerDependentBean(String beanName, String dependentBeanName);
String[] getDependentBeans(String beanName);
String[] getDependenciesForBean(String beanName);
// bean的銷毀相關方法
void destroyBean(String beanName, Object beanInstance);
void destroyScopedBean(String beanName);
void destroySingletons();
}
複制
這個接口定義了非常多的 API,按照用途來說,這些 API 大概分為三類:
- bean 的管理方法:包括 bean 依賴狀态與生命周期的擷取,bean 的銷毀,bean 作用域域、定義資訊與别名的操作;
- bean 建立過程中使用元件的配置:包括字元串解析器,類加載器,類型轉換器,屬性系統資料庫,bean 的後置處理器等元件的配置;
- 工廠本身狀态的一些操作:包括父工程配置,工廠間依賴的拷貝,以及通路控制等。
4、批量分層配置工廠
ConfigurableListableBeanFactory
是
BeanFactory
體系的第四級接口,也是最後一級接口。它繼承了
ConfigurableBeanFactory
、
ListableBeanFactory
與
AutowireCapableBeanFactory
接口,是以它具備到目前為止
BeanFactory
前三級接口定義的全部能力。
它表示了一個可以配置的,允許按單例或多例操作 bean,支援自動裝配 bean,并且可以根據 bean 的名稱、類型或者類上注解批量擷取 bean 的超級 bean 工廠。
它在上述功能的基礎上,又針對各接口提供的功能定義了一些新的補充方法:
public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
// 自動裝配相關配置
void ignoreDependencyType(Class<?> type);
void ignoreDependencyInterface(Class<?> ifc);
void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue);
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException;
// 擷取bean的定義資訊
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 擷取已經定義的bean名稱的疊代器
Iterator<String> getBeanNamesIterator();
// 清除bean元資訊緩存
void clearMetadataCache();
// 當機配置,當機後工廠的配置不允許進一步修改
void freezeConfiguration();
boolean isConfigurationFrozen();
// 執行個體化所有未執行個體化的單例bean
void preInstantiateSingletons() throws BeansException;
}
複制
二、ApplicationContext 接口體系
嚴格來說,
ApplicationContext
是
BeanFactory
的子類,或者說,
BeanFactory
是其組成的一部分。但是由于其附加了很多
BeanFactory
所不具備的功能,是以一般将其與
BeanFactory
體系分開看待。
ApplicationContext
有 web 環境上下文與非 web 環境上下文的兩個實作體系,單純按接口層次分為三層:
- 第一層:
;ApplicationContext
- 第二層:
和WebApplicationContext
;ConfigurableApplicationContext
- 第三層:
;ConfigurableApplicationContext
1、ApplicationContext
ApplicationContext
接口是基于
BeanFactory
的進一步實作,它同時實作了
EnvironmentCapable
,
ListableBeanFactory
,
HierarchicalBeanFactory
,
MessageSource
,
ApplicationEventPublisher
以及
ResourcePatternResolver
接口。相較
BeanFactory
,它的功能要更加強大。
ApplicationContext
繼承的各個接口分别對應它提供各項功能:
-
與HierarchicalBeanFactory
:提供像ListableBeanFactory
一樣操作 bean 的功能;BeanFactory
-
:提供向監聽器釋出事件的能力;ApplicationEventPublisher
-
與ResourcePatternResolver
:提供選擇性的某個特定環境的檔案資源中加載配置的能力;EnvironmentCapable
-
:提供解析消息并支援國際化配置的能力;MessageSource
結合它提供的功能和它的名稱,我們可以大概了解,與
BeanFactory
專門用于操作 bean 不同,
ApplicationContext
用于提供 spring 程式在某個特定環境運作時所具備的全部資訊的“上下文”對象,它之于
BeanFactory
,就像帶各種功能的超級保溫杯之于普通的水杯。
它定義的方法如下:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
// 擷取上下文id
String getId();
// 擷取對應應用程式名稱
String getApplicationName();
// 擷取上下文的展示名稱
String getDisplayName();
// 擷取容器被啟動的時間
long getStartupDate();
// 擷取父級上下文
ApplicationContext getParent();
// 擷取自動裝配bean工廠
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
複制
這裡可以看到,雖然
ApplicationContext
沒繼承
AutowireCapableBeanFactory
接口,但是他依然可以通過方法擷取到對應的裝配工廠。
2、web 應用上下文與可配置上下文
WebApplicationContext
WebApplicationContext
是 web 環境的上下文,該上下文幾乎沒有可配置項,主要用于配置
Servlet
上下文:
public interface WebApplicationContext extends ApplicationContext {
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
// 作用域
String SCOPE_REQUEST = "request";
String SCOPE_SESSION = "session";
String SCOPE_APPLICATION = "application";
// 固定的bean名稱
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
// 擷取ServletContext
ServletContext getServletContext();
}
複制
ConfigurableApplicationContext
ConfigurableApplicationContext
表示一個可以配置的上下文容器,與
WebApplicationContext
不同,它提供了一些參數和屬性的配置方法:
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
String ENVIRONMENT_BEAN_NAME = "environment";
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";
// 配置上下文的id
void setId(String id);
// 配置上下文父容器
void setParent(@Nullable ApplicationContext parent);
// 配置上下文允許環境
void setEnvironment(ConfigurableEnvironment environment);
@Override
ConfigurableEnvironment getEnvironment();
// 擷取bean後置處理器
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
// 添加一個應用監聽器,用于監聽ApplicationEventPublisher釋出的事件
void addApplicationListener(ApplicationListener<?> listener);
// 配置類加載器
void setClassLoader(ClassLoader classLoader);
// 配置資源協定處理器
void addProtocolResolver(ProtocolResolver resolver);
// 重新整理配置
void refresh() throws BeansException, IllegalStateException;
// 關閉此上下文容器時的回調函數
void registerShutdownHook();
// 關閉上下文容器,并釋放資源
void close();
// 目前容器是否已經調用過refresh(),并且尚未關閉
boolean isActive();
// 擷取bean工廠
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
複制
它有一個通用可配置上下文的實作類:
GenericApplicationContext
,在非 web 環境中,該實作類的兩個子類是最經常用到的:
-
:基于 xml 配置檔案配置的上下文;GenericXmlApplicationContext
-
:基于注解配置的上下文;AnnotationConfigApplicationContext
3、可配置的web應用上下文
ConfigurableApplicationContext
接口同時繼承了
WebApplicationContext
和
ConfigurableApplicationContext
,代表了一個可以配置的 web 上下文容器:
public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
String APPLICATION_CONTEXT_ID_PREFIX = WebApplicationContext.class.getName() +
String SERVLET_CONFIG_BEAN_NAME = "servletConfig";
// 配置Servlet容器
void setServletContext(@Nullable ServletContext servletContext);
void setServletConfig(@Nullable ServletConfig servletConfig);
@Nullable
ServletConfig getServletConfig();
// 設定命名空間
void setNamespace(@Nullable String namespace);
@Nullable
String getNamespace();
// 設定配置檔案的路徑,比如WEB-INF
void setConfigLocation(String configLocation);
void setConfigLocations(String... configLocations);
@Nullable
String[] getConfigLocations();
}
複制
一般 web 環境下執行個體化的上下文都為該接口的執行個體。
三、總結
在 spring 中,容器分為兩大類:
BeanFactory
和
ApplicationContext
。
BeanFactory
其中,
BeanFactory
是純粹的用于管理 bean 對象生命周期的容器,它的接口體系分為四層:
-
接口本身,是容器的最高層抽象;BeanFactory
-
:分層工廠,表示一個存在層級關系的容器;HierarchicalBeanFactory
:批量工廠,表示一個允許根據名稱、類型或類注解等屬性批量的操作 bean 的容器;ListableBeanFactory
:自動裝配工廠,表示一個可以關聯需要自動裝配的 bean 的容器;AutowireCapableBeanFactory
-
:分層配置工廠 ,是ConfigurableBeanFactory
和HierarchicalBeanFactory
接口的組合,表示一個分層的、可以以單例模式操作 bean,并且允許調整配置的容器;SingletonBeanRegistry
-
:可配置的批量工廠,是ConfigurableListableBeanFactory
與ConfigurableBeanFactory
接口的組合,具備AutowireCapableBeanFactory
體系中的全部能力。BeanFactory
ApplicationContext
ApplicationContext
是基于
BeanFactory
的擴充,它實作了其他的接口,是以具有一些
BeanFactory
不具備的功能:
-
:提供向監聽器釋出事件的功能;ApplicationEventPublisher
-
與ResourcePatternResolver
:提供選擇性的某個特定環境的檔案資源中加載配置的功能;EnvironmentCapable
-
:提供解析消息并支援國際化配置的功能;MessageSource
從層次來說,
ApplicationContext
主要分為三層:
-
接口本身,是基于ApplicationContext
接口的擴充,是整個應用上下文體系的最頂層接口;BeanFactory
-
:web 應用上下文,用于承載WebApplicationContext
;ServletContext
:用于非 web 環境下的可配置應用上下文;ConfigurableApplicationContext
-
:可配置的 web 應用上下文,同時繼承了ConfigurableApplicationContext
和WebApplicationContext
ConfigurableApplicationContext
接口,代表了一個可以配置的 web 上下文容器。
在一般的 web 環境中啟動的都是該上下文的執行個體。
釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/170762.html原文連結:https://javaforall.cn