本文尝试分析一下Spring 的 ApplicationContext体系的 接口设计,尝试理解为什么这么做,为什么接口这么设计、为什么这么去实现,为什么需要有这个方法,为什么 这样命名?接口、类、方法的 大致用途是什么? 是否是最合理的?是否有完善的空间? 是否 让一个 同样顶级人才来设计,是否会得到一样的 设计和实现?

简称:

BeanFactory 简称bf

ApplicationContext 简称ac

ServletContext 简称sc

BeanDefinition 简称bd

 

接口/类图

ac的 uml 接口/类图 如下:

以AnnotationConfigServletWebServerApplicationContext 的视角来看(ctrl+shift+alt+U)

可以看到 ac 继承了很多的bf  接口,另外,关键的还有 ResourceLoader 接口, 这里的 Resource 我认为主要就是 bd, properties文件呢? 应该是另外的话题 。

abstract ac 的下级子类 :

DefaultResourceLoader (org.springframework.core.io)
AbstractApplicationContext (org.springframework.context.support)
AbstractRefreshableApplicationContext (org.springframework.context.support)
AbstractRefreshableConfigApplicationContext (org.springframework.context.support)
AnnotationConfigReactiveWebApplicationContext (org.springframework.boot.web.reactive.context)
AbstractXmlApplicationContext (org.springframework.context.support)
FileSystemXmlApplicationContext (org.springframework.context.support)
ClassPathXmlApplicationContext (org.springframework.context.support)
AbstractRefreshableWebApplicationContext (org.springframework.web.context.support)
XmlWebApplicationContext (org.springframework.web.context.support)
GroovyWebApplicationContext (org.springframework.web.context.support)
AnnotationConfigWebApplicationContext (org.springframework.web.context.support)
GenericApplicationContext (org.springframework.context.support)
GenericXmlApplicationContext (org.springframework.context.support)
StaticApplicationContext (org.springframework.context.support)
StaticWebApplicationContext (org.springframework.web.context.support)
GenericWebApplicationContext (org.springframework.web.context.support)
ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
AnnotationConfigServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
XmlServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
ResourceAdapterApplicationContext (org.springframework.jca.context)
GenericGroovyApplicationContext (org.springframework.context.support)
AnnotationConfigApplicationContext (org.springframework.context.annotation)
GenericReactiveWebApplicationContext (org.springframework.boot.web.reactive.context)
ReactiveWebServerApplicationContext (org.springframework.boot.web.reactive.context)
AnnotationConfigReactiveWebServerApplicationContext (org.springframework.boot.web.reactive.context)

接口描述

================================== ApplicationContext ==================================

ac 定义如下:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

String getId();

String getApplicationName();// ApplicationName 和 id 什么区别?

String getDisplayName();

long getStartupDate();

@Nullable
ApplicationContext getParent(); // Nullable表示 可能没有 父

AutowireCapableBeanFactory getAutowireCapableBeanFactory()
}

非常简单,似乎并没有什么实用的 功能特性..

ApplicationContext 全是 get(获取)属性:id、applicationName、displayName、startupDate、parent、autowireCapableBeanFactory
注意这里的parent 是ApplicationContext,而 HierarchicalBeanFactory 的 parentBeanFactory 是BeanFactory 类型

================================== 插播 ==================================

public interface Lifecycle {
void start();

void stop();

boolean isRunning();
}

AliasRegistry: 对alias 的增删改查

public interface AliasRegistry {
void registerAlias(String var1, String var2);

void removeAlias(String var1);

boolean isAlias(String var1);

String[] getAliases(String var1);
}

BeanDefinitionRegistry 对bd 的增删改查
—— XxxRegistry 命名格式的类 有什么特殊?
—— 注意 一个name只对应一个bd,正如一个name对应一个bean; 一一对应关系!
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;

void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

boolean containsBeanDefinition(String var1);

String[] getBeanDefinitionNames();

int getBeanDefinitionCount();

boolean isBeanNameInUse(String var1);
}

================================== WebApplicationContext ==================================
WebApplicationContext
关键是可以获取Servlet上下文 ServletContext

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";
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";

@Nullable
ServletContext getServletContext(); // 关键方法!!!
}

================================== WebServerApplicationContext ==================================

WebServerApplicationContext 可以获取属性:webServer、serverNamespace, 分别是什么作用??
webServer是对 Tomcat、jetty 的抽象,代表可以运行的web 服务器程序
serverNamespace 是

public interface WebServerApplicationContext extends ApplicationContext {
WebServer getWebServer();
String getServerNamespace();
}

++++++++++++++++++++++++++++++++++ ConfigurableApplicationContext ++++++++++++++++++++++++++++++++++
ConfigurableApplicationContext

Configurable 可配置,可配置什么?id、parent、env、添加BeanFactoryPostProcessor、添加ApplicationListener、添加ProtocolResolver
这里的配置 是设置的 意思! 作为一个接口,它可以设置x属性意味着什么,意味着它必然可以获取那个x!
BeanFactoryPostProcessor 是一个非常强大的东西,可以添加BeanFactoryPostProcessor,意味着可以对bf很多扩展,可以玩出花来!
ApplicationListener 是做监听等作用。
ProtocolResolver是..

注意 这个类涉及比较多的Environment操作, 既可以set也可以get,全能Environment 选手。
而且这里的Environment 又是Configurable的

定义如下:
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";

void setId(String var1);

void setParent(@Nullable ApplicationContext var1);

void setEnvironment(ConfigurableEnvironment var1);

ConfigurableEnvironment getEnvironment();

void addBeanFactoryPostProcessor(BeanFactoryPostProcessor var1);

void addApplicationListener(ApplicationListener<?> var1);

void addProtocolResolver(ProtocolResolver var1);

void refresh() throws BeansException, IllegalStateException; // 重要方法,首次定义!

void registerShutdownHook();

void close();

boolean isActive();

ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}

================================== ConfigurableWebServerApplicationContext ==================================

ConfigurableWebServerApplicationContext 额外继承了 WebServerApplicationContext, 主要有set serverNamespace 方法

———— 为什么要分这么细? 这里的set ServerNamespace 不能合并到 WebServerApplicationContext?分这么细? ———— 主要是 体现一个 Configurable!!~
———— Configurable类,一定有 set方法 ?好像是这样

public interface ConfigurableWebServerApplicationContext extends ConfigurableApplicationContext, WebServerApplicationContext {
void setServerNamespace(String serverNamespace);
}

================================== ConfigurableWebApplicationContext ==================================

它跟 ConfigurableWebServerApplicationContext 非常类似, 容易混淆。 区分一下:
Configurable Web ac extends ConfigurableApplicationContext, Web ac
Configurable Web Server ac extends ConfigurableApplicationContext, Web Server ac
接口 名字差别仅仅是 一个单词 Server, 继承的父 接口也是 差别同一个单词

ConfigurableWebApplicationContext
Configurable 可配置,可配置什么? 设置sc、Namespace、ServletConfig、ConfigLocation,并可以获取Namespace、ServletConfig、 ConfigLocation (基本上就是同时getter、setter)—— 这些都是webapp 必须的东西!
sc的getter呢? WebApplicationContext 定义的!
可以看到,虽然是少了个单词Server,但是它的 方法比 Configurable Web Server ac 多一些。它才是 主接口!

定义如下:
public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
String APPLICATION_CONTEXT_ID_PREFIX = WebApplicationContext.class.getName() + ":";
String SERVLET_CONFIG_BEAN_NAME = "servletConfig";

void setServletContext(@Nullable ServletContext var1);

void setServletConfig(@Nullable ServletConfig var1);

@Nullable
ServletConfig getServletConfig();

void setNamespace(@Nullable String var1);

@Nullable
String getNamespace();

void setConfigLocation(String var1);

void setConfigLocations(String... var1);

@Nullable
String[] getConfigLocations();
}

接口实现说明

++++++++++++++++++++++++++++++++++ AbstractApplicationContext ++++++++++++++++++++++++++++++++++

AbstractApplicationContext 是一个重量级的 类: 很重,他的主要内容 就是 实现了哪些个接口,最重要的方法是 refresh, 其他的方法几乎都是为了而存在的。其他的私有方法更加如此。几乎可以忽略。 简单来说,它 bf,Configurable,Listable,具有ac特性,Hierarchical, 国际化特性, lifecycle特性
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
...
}

它继承了ConfigurableApplicationContext,但是呢,似乎没有任何 web 的功能!!!!

方法
AbstractApplicationContext()
AbstractApplicationContext(context.ApplicationContext)
setDisplayName
createEnvironment
publishEvent(java.lang.Object, core.ResolvableType)
getApplicationEventMulticaster
getLifecycleProcessor
getResourcePatternResolver
getBeanFactoryPostProcessors
getApplicationListeners
prepareRefresh
initPropertySources
obtainFreshBeanFactory
prepareBeanFactory
postProcessBeanFactory
invokeBeanFactoryPostProcessors
registerBeanPostProcessors
initMessageSource
initApplicationEventMulticaster
initLifecycleProcessor
onRefresh
registerListeners
finishBeanFactoryInitialization
finishRefresh
cancelRefresh
resetCommonCaches
destroy
doClose
destroyBeans
onClose
assertBeanFactoryActive
getInternalParentBeanFactory //
getMessageSource
getInternalParentMessageSource
refreshBeanFactory
closeBeanFactory

MESSAGE_SOURCE_BEAN_NAME
LIFECYCLE_PROCESSOR_BEAN_NAME
APPLICATION_EVENT_MULTICASTER_BEAN_NAME

属性, 同时有getter、setter
logger
id
displayName
parent ApplicationContext
environment ConfigurableEnvironment
beanFactoryPostProcessors List<BeanFactoryPostProcessor>
startupDate
active
closed
startupShutdownMonitor Object
shutdownHook Thread
resourcePatternResolver ResourcePatternResolver
lifecycleProcessor LifecycleProcessor
messageSource MessageSource
applicationEventMulticaster
applicationListeners Set<ApplicationListener<?>>
earlyApplicationEvents Set<ApplicationEvent>

对 其他
ConfigurableApplicationContext:
setId
setEnvironment
getEnvironment
setParent
addBeanFactoryPostProcessor
addApplicationListener
refresh // !!!!!!!! 最最重要的 实现方法 在此, 是核心, 是关键。 其他大部分方法因她存在 !!!!!!!!
registerShutdownHook
close
isActive

ConfigurableApplicationContext:
getBeanFactory

ApplicationContext:
getId
getApplicationName
getDisplayName
getParent
getAutowireCapableBeanFactory
getStartupDate

ApplicationEventPublisher:
publishEvent(context.ApplicationEvent)
publishEvent(java.lang.Object)

bf:
getBean(java.lang.String) // 这里的 很多方法, 其实是代理方法,具体的工作实际上是内部的 BeanFactory 代理完成的 !
getBean(java.lang.String, java.lang.Class<T>)
getBean(java.lang.String, java.lang.Object...)
getBean(java.lang.Class<T>)
getBean(java.lang.Class<T>, java.lang.Object...)
containsBean
isSingleton
isPrototype
isTypeMatch(java.lang.String, core.ResolvableType)
isTypeMatch(java.lang.String, java.lang.Class<?>)
getType
getAliases

ListableBeanFactory: // 这里的 很多方法, 其实是代理方法,具体的工作实际上是内部的 BeanFactory 代理完成的 !
containsBeanDefinition
getBeanDefinitionCount
getBeanDefinitionNames
getBeanNamesForType(core.ResolvableType)
getBeanNamesForType(java.lang.Class<?>)
getBeanNamesForType(java.lang.Class<?>, boolean, boolean)
getBeansOfType(java.lang.Class<T>)
getBeansOfType(java.lang.Class<T>, boolean, boolean)
getBeanNamesForAnnotation
getBeansWithAnnotation
findAnnotationOnBean

HierarchicalBeanFactory: // 这里的 很多方法, 其实是代理方法,具体的工作实际上是内部的 BeanFactory 代理完成的 !
getParentBeanFactory
containsLocalBean

MessageSource: // 这里的 方法, 也是代理方法 this.getMessageSource().xx
getMessage(java.lang.String, java.lang.Object[], java.lang.String, java.util.Locale)
getMessage(java.lang.String, java.lang.Object[], java.util.Locale)
getMessage(context.MessageSourceResolvable, java.util.Locale)
getResources

Lifecycle:
start
stop
isRunning

toString
AbstractApplicationContext()

++++++++++++++++++++++++++++++++++ GenericApplicationContext ++++++++++++++++++++++++++++++++++

GenericApplicationContext 在上面的 abstract ac 上增加了 bd registry 的功能,同时覆盖或 实现了某些aac 的方法:
是一个基础的、通用的 ac
主要的实现逻辑是: 实例化一个 DefaultListableBeanFactory,ResourceLoader 可以配置化,

新增的 重要方法 : registerBean, 可以直接注册bd对应的类型,而不用设置name,name则通过BeanDefinitionCustomizer设置。

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

setParent
getResources
cancelRefresh
getAutowireCapableBeanFactory

getResource
setClassLoader
getClassLoader

refreshBeanFactory
closeBeanFactory
getBeanFactory

registerBeanDefinition
removeBeanDefinition
getBeanDefinition
isBeanNameInUse

registerAlias
removeAlias
isAlias

GenericApplicationContext()
GenericApplicationContext(beans.factory.support.DefaultListableBeanFactory)
GenericApplicationContext(context.ApplicationContext)
GenericApplicationContext(beans.factory.support.DefaultListableBeanFactory, context.ApplicationContext)
setAllowBeanDefinitionOverriding
setAllowCircularReferences
setResourceLoader
getDefaultListableBeanFactory

///////// 新增的 重要方法 !
registerBean(java.lang.Class<T>, beans.factory.config.BeanDefinitionCustomizer...)
registerBean(java.lang.String, java.lang.Class<T>, beans.factory.config.BeanDefinitionCustomizer...)
registerBean(java.lang.Class<T>, java.util.function.Supplier<T>, beans.factory.config.BeanDefinitionCustomizer...)
registerBean(java.lang.String, java.lang.Class<T>, java.util.function.Supplier<T>, beans.factory.config.BeanDefinitionCustomizer...)

beanFactory DefaultListableBeanFactory
resourceLoader ResourceLoader
customClassLoader boolean
refreshed AtomicBoolean

resourceLoader: ResourceLoader
allowBeanDefinitionOverriding: boolean
allowCircularReferences: boolean
defaultListableBeanFactory: DefaultListableBeanFactory

public void setParent(@Nullable ApplicationContext parent) {
super.setParent(parent);
this.beanFactory.setParentBeanFactory(this.getInternalParentBeanFactory());
}

public interface BeanDefinitionCustomizer {
void customize(BeanDefinition var1);
}

++++++++++++++++++++++++++++++++++ GenericWebApplicationContext ++++++++++++++++++++++++++++++++++

主要是实现了 postProcessBeanFactory 方法,另外很多的方法是 UnsupportedOperationException,需要子类实现。

public class GenericWebApplicationContext extends GenericApplicationContext implements ConfigurableWebApplicationContext, ThemeSource {

GenericWebApplicationContext
setServletContext
setServletConfig
getServletConfig UnsupportedOperationException
setNamespace
getNamespace UnsupportedOperationException
setConfigLocation UnsupportedOperationException
setConfigLocations UnsupportedOperationException
getConfigLocations UnsupportedOperationException

getServletContext

getApplicationName

createEnvironment
postProcessBeanFactory
onRefresh
initPropertySources
getResourcePatternResolver

getResourceByPath

getTheme

GenericWebApplicationContext()
GenericWebApplicationContext(javax.servlet.ServletContext)
GenericWebApplicationContext(support.DefaultListableBeanFactory)
GenericWebApplicationContext(support.DefaultListableBeanFactory, javax.servlet.ServletContext)

主要属性:
servletContext
themeSource


@Nullable
private ServletContext servletContext;
@Nullable
private ThemeSource themeSource;

可见, 它几乎仅仅是提供了 servletContext themeSource 的属性配置功能。

另外,postProcessBeanFactory 比较重要:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
if (this.servletContext != null) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}

WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}

++++++++++++++++++++++++++++++++++ ServletWebServerApplicationContext ++++++++++++++++++++++++++++++++++

ServletWebServerApplicationContext 是 Spring boot 的内容。

主要实现了 ConfigurableWebServerApplicationContext, GenericWebApplicationContext
通过实现 Servlet,实现了 WebServer 的大部分逻辑,实现了很多的 ConfigurableWebServerApplicationContext 的空方法
主要方法是 createWebServer startWebServer stopAndReleaseWebServer ... 另外 selfInitialize 也做了一些事情

然后是 prepareWebApplicationContext(ServletContext servletContext) ,
Object rootContext = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); // this
this.setServletContext(servletContext);

WebApplicationContextUtils registerWebApplicationScopes

WebApplicationContextUtils registerEnvironmentBeans

补充:
ServletContextInitializer
public interface ServletContextInitializer {
void onStartup(ServletContext servletContext) throws ServletException;
}

ExistingWebApplicationScopes
restore

定义如下:
public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext {

}

ServletWebServerApplicationContext
ExistingWebApplicationScopes
ExistingWebApplicationScopes#null
ExistingWebApplicationScopes#ExistingWebApplicationScopes
ExistingWebApplicationScopes#restore
ExistingWebApplicationScopes#SCOPES
ExistingWebApplicationScopes#beanFactory
ExistingWebApplicationScopes#scopes
postProcessBeanFactory
onRefresh
getResourceByPath
setServletConfig
getServletConfig
refresh // 这里的 refresh 是主要是异常处理,具体工作是 super.refresh();
finishRefresh
onClose
getServerNamespace
getWebServer
setServerNamespace
ServletWebServerApplicationContext()
ServletWebServerApplicationContext(support.DefaultListableBeanFactory)
createWebServer
selfInitialize
prepareWebApplicationContext
startWebServer
stopAndReleaseWebServer
getWebServerFactory
getSelfInitializer
getServletContextInitializerBeans

logger
DISPATCHER_SERVLET_NAME

主要属性:
webServer
servletConfig
serverNamespace

++++++++++++++++++++++++++++++++++ TomcatWebServer ++++++++++++++++++++++++++++++++++

public interface WebServer {
void start() throws WebServerException;

void stop() throws WebServerException;

int getPort();
}

public class TomcatWebServer implements WebServer {..

TomcatWebServer
start
stop
TomcatWebServer
TomcatWebServer
initialize
findContext
addInstanceIdToEngineName
removeServiceConnectors
rethrowDeferredStartupExceptions
startDaemonAwaitThread
checkThatConnectorsHaveStarted
stopSilently
stopTomcat
addPreviouslyRemovedConnectors
stopProtocolHandler
performDeferredLoadOnStartup
getPortsDescription
logger
containerCounter
monitor
autoStart
started

++++++++++++++++++++++++++++++++++ 补充 ++++++++++++++++++++++++++++++++++

AnnotationConfigRegistry 是一个简单的类, 通过class 注册 ,通过 scan扫描 package name 解析 annotation 注解,然后再调用第一个方法去 register 扫描到的class 实例
public interface AnnotationConfigRegistry {
void register(Class<?>... var1);
void scan(String... var1);
}

public interface BeanNameGenerator {
String generateBeanName(BeanDefinition var1, BeanDefinitionRegistry var2);
}

ScopeMetadataResolver 有些难理解。。
public interface ScopeMetadataResolver {
ScopeMetadata resolveScopeMetadata(BeanDefinition var1);
}

++++++++++++++++++++++++++++++++++ AnnotationConfigServletWebServerApplicationContext ++++++++++++++++++++++++++++++++++

AnnotationConfigServletWebServer ac 是集大成者, 通过一系列的集成, 它已经非常的丰满。它大部分是一些set/get,主要方法是 postProcessBeanFactory

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.postProcessBeanFactory(beanFactory);
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}

if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}

可以看到, 它主要是 先通过scanner.scan 去扫描 获取bd,放置到 registry(也就是自身, registry 也是bf,因为bf 继承了registry), 然后调用 reader.register,(reader 也是bf,因为bf),scanner、reader 都拥有 自身的引用,他们相互引用。。。 这样完后,AnnotationConfigServletWebServer ac 它自己就可以获取所有的bd,也有拥有了所有的 bd!

实际上scanner.scan、reader.register 是很耗时的, 里面的处理逻辑非常的复杂,特别是涉及到 ConfigurationClass 这一块。 因为它的 功能实在太强大。(后续展开)

签名:
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {

}

AnnotationConfigServletWebServerApplicationContext
prepareRefresh
setEnvironment
register
scan
postProcessBeanFactory
AnnotationConfigServletWebServerApplicationContext()
AnnotationConfigServletWebServerApplicationContext(support.DefaultListableBeanFactory)
AnnotationConfigServletWebServerApplicationContext(java.lang.Class<?>...)
AnnotationConfigServletWebServerApplicationContext(java.lang.String...)

setBeanNameGenerator
setScopeMetadataResolver

主要属性:
reader AnnotatedBeanDefinitionReader
scanner ClassPathBeanDefinitionScanner
annotatedClasses Set<Class<?>>
basePackages String[]


private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
private final Set<Class<?>> annotatedClasses;
private String[] basePackages;

++++++++++++++++++++++++++++++++++ AbstractRefreshableApplicationContext ++++++++++++++++++++++++++++++++++

签名:
public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext implements ConfigurableWebApplicationContext, ThemeSource {

}

refreshBeanFactory
closeBeanFactory
getBeanFactory
cancelRefresh
assertBeanFactoryActive
AbstractRefreshableApplicationContext()
AbstractRefreshableApplicationContext(org.springframework.context.ApplicationContext)
hasBeanFactory
createBeanFactory
customizeBeanFactory
loadBeanDefinitions
setAllowBeanDefinitionOverriding
setAllowCircularReferences
allowBeanDefinitionOverriding
allowCircularReferences
beanFactory
beanFactoryMonitor

主要属性是:
@Nullable
private Boolean allowBeanDefinitionOverriding;
@Nullable
private Boolean allowCircularReferences;
@Nullable
private DefaultListableBeanFactory beanFactory;
private final Object beanFactoryMonitor = new Object();

主要方法是
protected final void refreshBeanFactory() throws BeansException {
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}

try {
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
this.loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}

实现了 客制化! 让 allowCircularReferences allowBeanDefinitionOverriding 属性 可配置!

++++++++++++++++++++++++++++++++++ AbstractRefreshableConfigApplicationContext ++++++++++++++++++++++++++++++++++

签名:
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext implements BeanNameAware, InitializingBean {
}

setId
setBeanName
afterPropertiesSet
AbstractRefreshableConfigApplicationContext()
AbstractRefreshableConfigApplicationContext(org.springframework.context.ApplicationContext)
resolvePath
getConfigLocations
configLocations
setConfigLocation
setConfigLocations
getDefaultConfigLocations
setIdCalled

主要属性是:
private String[] configLocations;
private boolean setIdCalled = false;
可见, 主要是提供了 config文件的位置的 配置化!

++++++++++++++++++++++++++++++++++ AbstractRefreshableWebApplicationContext ++++++++++++++++++++++++++++++++++

AbstractRefreshableWebApplicationContext

签名:
public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext implements ConfigurableWebApplicationContext, ThemeSource {
}

@Nullable
private ServletContext servletContext;
@Nullable
private ServletConfig servletConfig;
@Nullable
private String namespace;
@Nullable
private ThemeSource themeSource;

AbstractRefreshableWebApplicationContext
setServletContext
setServletConfig
getServletConfig
setNamespace
getNamespace
getConfigLocations
getServletContext
getApplicationName
createEnvironment
postProcessBeanFactory
onRefresh
initPropertySources
getResourcePatternResolver
getResourceByPath
getTheme
AbstractRefreshableWebApplicationContext

主要属性:
servletContext
servletConfig
namespace
themeSource

其实主要就是提供了 servletContext servletConfig namespace 的getter、setter 然后在 postProcessBeanFactory 进行各种 后处理:

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

++++++++++++++++++++++++++++++++++ AbstractXmlApplicationContext ++++++++++++++++++++++++++++++++++

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
}

AbstractXmlApplicationContext
AbstractXmlApplicationContext
initBeanDefinitionReader
loadBeanDefinitions
setValidating

validating //重要属性

++++++++++++++++++++++++++++++++++ FileSystemXmlApplicationContext ++++++++++++++++++++++++++++++++++

主要是提供了 多个构造函数, 可以通过指定 xml文件的 FileSystem 位置来 配置 ac
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
}

++++++++++++++++++++++++++++++++++ ClassPathXmlApplicationContext ++++++++++++++++++++++++++++++++++

主要是提供了 多个构造函数, 可以通过指定 xml文件的 ClassPath 位置来 配置 ac
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
}

主要属性是:
private Resource[] configResources;

ClassPath 和 FileSystem 有什么区别? 有细微的。。

++++++++++++++++++++++++++++++++++ XmlWebApplicationContext ++++++++++++++++++++++++++++++++++

签名:
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {

}

XmlWebApplicationContext

主要方法是
getDefaultConfigLocations
initBeanDefinitionReader
loadBeanDefinitions(support.DefaultListableBeanFactory)
loadBeanDefinitions(xml.XmlBeanDefinitionReader) // 重要方法: 通过XmlBeanDefinitionReader,读取xml,解析为 bd

public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";

namespace 的作用? 如何配置?
protected String[] getDefaultConfigLocations() {
return this.getNamespace() != null ? new String[]{"/WEB-INF/" + this.getNamespace() + ".xml"} : new String[]{"/WEB-INF/applicationContext.xml"};
}

org.xml.sax.InputSource
InputSource()
InputSource(java.lang.String)
InputSource(java.io.InputStream)
InputSource(java.io.Reader)

++++++++++++++++++++++++++++++++++ AnnotationConfigWebApplicationContext ++++++++++++++++++++++++++++++++++

public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext implements AnnotationConfigRegistry {
}

register
scan
loadBeanDefinitions // 主要方法!!!!重量级方法, 这里调用了 scanner、reader 的方法
AnnotationConfigWebApplicationContext
getAnnotatedBeanDefinitionReader
getClassPathBeanDefinitionScanner
setBeanNameGenerator
getBeanNameGenerator
beanNameGenerator
setScopeMetadataResolver
getScopeMetadataResolver

主要属性是:
scopeMetadataResolver
annotatedClasses
basePackages


private BeanNameGenerator beanNameGenerator;
@Nullable
private ScopeMetadataResolver scopeMetadataResolver;
private final Set<Class<?>> annotatedClasses = new LinkedHashSet();
private final Set<String> basePackages = new LinkedHashSet();

AnnotationConfigWebApplicationContext 竟然 不继承 AnnotationConfigApplicationContext,而两者的名字 如此的 接近! 一个是AnnotationConfig ,一个是AnnotationConfigWeb, 为什么要分这么细?对比发现, AnnotationConfigWebApplicationContext 似乎要少了 几个方法...

总结

观察可发现,几乎 对应每一个 类型的bf, 都有一个ac,比如listable,configurable。 ac 的功能比bf 要强大不少,当然,也复杂不少。有了ac,我们的程序就可以跑起来了。 那么什么时候我们使用ac? 什么时候用bf? 我觉得一般都是直接使用ac,bf 几乎用不得,除非底层研究的时候!

ac 意味着一个应用程序,相当于bf 屌丝,ac 其实已经是 高富帅。他提供了很多的 高级特性,可以直接作为application 可以实际应用,可生产环境部署 ,ac 的子接口  主要都是Web,这也 好理解, Spring的主要 适用领悟是 Web application

ac 的功能特性太多,部分还有疑问,待续。

最后的记忆——Spring ApplicationContext的更多相关文章

  1. 以静态变量保存 Spring ApplicationContext

    package com.thinkgem.jeesite.common.utils; import java.net.HttpURLConnection; import java.net.URL; i ...

  2. Spring ApplicationContext(一)初始化过程

    Spring 容器 ApplicationContext(一)初始化过程 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) ...

  3. Spring ApplicationContext(二)环境准备

    Spring ApplicationContext(二)环境准备 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 本节介绍 ...

  4. Spring ApplicationContext(五)invokeBeanFactoryPostProcessors

    Spring ApplicationContext(六)BeanPostProcessor 产生回顾一下 ApplicationContext 初始化的几个步骤:第一步是刷新环境变量:第二步是刷新 b ...

  5. Spring ApplicationContext(六)BeanPostProcessor

    Spring ApplicationContext(六)BeanPostProcessor 产生回顾一下 ApplicationContext 初始化的几个步骤:第一步是刷新环境变量:第二步是刷新 b ...

  6. Spring ApplicationContext(八)事件监听机制

    Spring ApplicationContext(八)事件监听机制 本节则重点关注的是 Spring 的事件监听机制,主要是第 8 步:多播器注册:第 10 步:事件注册. public void ...

  7. Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/config/spring/applicationContext.xml]

    在搭建SpringMVC框架的时候遇到了这个问题 问题的原因: 就是没有找到applicatoincontext.xml这个文件, 因为idea自动生成的路径不正确 因此需要再web.xml里面, ( ...

  8. 使用Arthas 获取Spring ApplicationContext还原问题现场

    ## 背景 最近来了个实习僧小弟,安排他实现对目标网站 连通性检测的小功能,简单讲就是将下边的shell 脚本换成Java 代码来实现 ``` 1#!/bin/bash 2URL="http ...

  9. 从一个简单的例子看spring ApplicationContext上下文隔离

    前言 某天,浏览博客园的时候,对首页上面的一篇文章,标题为:<<一个普通类就能干趴你的springboot,你信吗?>>,文章链接:https://www.cnblogs.co ...

随机推荐

  1. VLAN实验1(VLAN基础配置及Access接口)

    本实验基于<HCNA网 络技术实验指南> 本实验使用eNSP软件 原理概述: 早期的局域网技术是基于总线型结构的.总线型拓扑结构是由一根单电缆连接着所 有主机,这种局域网技术存在着冲突域问 ...

  2. 对python的初步了解

    一,Python简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具 ...

  3. fsockopen与HTTP 1.1/HTTP 1.0

    在前面的例子中,HTTP请求信息头有些指定了 HTTP 1.1,有些指定了 HTTP/1.0,有些又没有指定,那么他们之间有什么区别呢? 关于HTTP 1.1与HTTP 1.0的一些基本情况,可以参考 ...

  4. BZOJ 3108: [cqoi2013]图的逆变换

    3108: [cqoi2013]图的逆变换 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 627  Solved: 415[Submit][Statu ...

  5. 原生js 复制内容到剪切板

    代码: function copyHandle(content){ let copy = (e)=>{ e.preventDefault() e.clipboardData.setData('t ...

  6. linux 通过管道更方便的查询输入记录

    history |sort -k4|uniq -f3 -c |sort -n -k2 history:得到输入记录|sort -k4:在第4列进行排序 -k4 第4列 每一列用空格分隔|uniq -f ...

  7. bash单引号嵌套

    转自:https://blog.jysoftware.com/2015/12/bash-%E6%80%8E%E4%B9%88%E5%81%9A%E5%8D%95%E5%BC%95%E5%8F%B7%E ...

  8. 使用aop切面编写日志模块

    我们先自定义一个注解(一个有关自定义注解的LJ文章 https://www.cnblogs.com/guomie/p/10824973.html) /** * * 自定义日志注解 * Retentio ...

  9. 【Vuejs】350- 学习 Vue 源码的必要知识储备

    前言 我最近在写 Vue 进阶的内容.在这个过程中,有些人问我看 Vue 源码需要有哪些准备吗?所以也就有了这篇计划之外的文章. 当你想学习 Vue 源码的时候,需要有扎实的 JavaScript 基 ...

  10. Nginx(一)--nginx的初步认识及配置

    什么是Nginx 是一个高性能的反向代理服务器正向代理代理的是客户端反向代理代理的是服务端 Apache.Tomcat.Nginx 静态web服务器jsp/servlet服务器 tomcat 安装Ng ...