本文需要有前4篇文章的基礎(chǔ),才能夠清晰易懂,有興趣可以先看看詳細(xì)的流程,這篇文章可以說(shuō)是第1篇文章,也能夠說(shuō)是前4篇文章的的匯總,Spring的全部要求流程都是圍繞著
DispatcherServlet
進(jìn)行的
根據(jù)類的結(jié)構(gòu)來(lái)講DispatcherServlet本身也是繼承了HttpServlet的,所有的要求都是根據(jù)這1個(gè)Servlet來(lái)進(jìn)行轉(zhuǎn)發(fā)的,同時(shí)解釋了為何需要在web.xml進(jìn)行以下配置,由于Spring是基于1個(gè)Servlet來(lái)展開的,固然不需要Servlet也能夠使用Spring
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
protected void initStrategies(ApplicationContext context) {
//初始化文件上傳處理類
initMultipartResolver(context);
//初始化本地化Resolver
initLocaleResolver(context);
//初始化主題Resolver
initThemeResolver(context);
//初始化1些個(gè)與處理的HandlerMappings
initHandlerMappings(context);
//
initHandlerAdapters(context);
//初始化異常處理的handler
initHandlerExceptionResolvers(context);
//初始化要求路徑轉(zhuǎn)換為ViewName 的Translator
initRequestToViewNameTranslator(context);
//初始化ViewResolvers 這個(gè)就是針對(duì)視圖處理的Resolvers 比如jsp處理Resolvers 或freemarker處理Resolvers
initViewResolvers(context);
//初始化 主要管理flashmap,比如RedirectAttributes 的屬性會(huì)放到這個(gè)里面,默許使用的是SessionFlashMapManager
initFlashMapManager(context);
}
HttpServletBean
本身來(lái)講是1個(gè)普通的servlet而已,主要做1些資源的初始化
public abstract class HttpServletBean extends HttpServlet
implements EnvironmentCapable, EnvironmentAware {
protected final Log logger = LogFactory.getLog(getClass());
/**
* Set of required properties (Strings) that must be supplied as
* config parameters to this servlet.
*/
private final Set<String> requiredProperties = new HashSet<String>();
private ConfigurableEnvironment environment;
/**
* Subclasses can invoke this method to specify that this property
* (which must match a JavaBean property they expose) is mandatory,
* and must be supplied as a config parameter. This should be called
* from the constructor of a subclass.
* <p>This method is only relevant in case of traditional initialization
* driven by a ServletConfig instance.
* @param property name of the required property
*/
protected final void addRequiredProperty(String property) {
this.requiredProperties.add(property);
}
/**
* Map config parameters onto bean properties of this servlet, and
* invoke subclass initialization.
* @throws ServletException if bean properties are invalid (or required
* properties are missing), or if subclass initialization fails.
*/
@Override
public final void init() throws ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
}
// Set bean properties from init parameters.
try {
//使用Servlet配置的初始化參數(shù)創(chuàng)建1個(gè)PropertyValues對(duì)象,PropertyValues對(duì)象是名值對(duì)的集合, 子類也能夠指定哪些屬性是必須的
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
//把當(dāng)前的Servlet當(dāng)作1個(gè)Bean, 把Bean的屬性和屬性的存取方法信息放入BeanWrapper對(duì)象
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
//注冊(cè)1個(gè)可以在資源和路徑之間進(jìn)行轉(zhuǎn)化的客戶化編輯器,這些資源是這個(gè)Web利用的內(nèi)部資源,例如,1個(gè)文件,1個(gè)圖片等等
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
//提供給子類機(jī)會(huì)增加更多的客戶化的編輯器,或?qū)eanWrapper進(jìn)行更多的初始化
initBeanWrapper(bw);
//把初始化制定的參數(shù)值賦值到Servlet的屬性中,第2個(gè)參數(shù)true表明疏忽位置屬性
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
throw ex;
}
// Let subclasses do whatever initialization they like.
//提供給子類的的初始化方法 目前是FrameworkServlet 進(jìn)行了實(shí)現(xiàn)
initServletBean();
if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
}
/**
* Initialize the BeanWrapper for this HttpServletBean,
* possibly with custom editors.
* <p>This default implementation is empty.
* @param bw the BeanWrapper to initialize
* @throws BeansException if thrown by BeanWrapper methods
* @see org.springframework.beans.BeanWrapper#registerCustomEditor
*/
protected void initBeanWrapper(BeanWrapper bw) throws BeansException {
}
/**
* Overridden method that simply returns {@code null} when no
* ServletConfig set yet.
* @see #getServletConfig()
*/
@Override
public final String getServletName() {
return (getServletConfig() != null ? getServletConfig().getServletName() : null);
}
/**
* Overridden method that simply returns {@code null} when no
* ServletConfig set yet.
* @see #getServletConfig()
*/
@Override
public final ServletContext getServletContext() {
return (getServletConfig() != null ? getServletConfig().getServletContext() : null);
}
/**
* Subclasses may override this to perform custom initialization.
* All bean properties of this servlet will have been set before this
* method is invoked.
* <p>This default implementation is empty.
* @throws ServletException if subclass initialization fails
*/
protected void initServletBean() throws ServletException {
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if environment is not assignable to
* {@code ConfigurableEnvironment}.
*/
@Override
public void setEnvironment(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
this.environment = (ConfigurableEnvironment) environment;
}
/**
* {@inheritDoc}
* <p>If {@code null}, a new environment will be initialized via
* {@link #createEnvironment()}.
*/
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = this.createEnvironment();
}
return this.environment;
}
/**
* Create and return a new {@link StandardServletEnvironment}. Subclasses may override
* in order to configure the environment or specialize the environment type returned.
*/
protected ConfigurableEnvironment createEnvironment() {
return new StandardServletEnvironment();
}
/**
* PropertyValues implementation created from ServletConfig init parameters.
*/
//主要是用來(lái)添加初始化參數(shù)的
private static class ServletConfigPropertyValues extends MutablePropertyValues {
/**
* Create new ServletConfigPropertyValues.
* @param config ServletConfig we'll use to take PropertyValues from
* @param requiredProperties set of property names we need, where
* we can't accept default values requiredProperties 這個(gè)參數(shù)主要是指定初始化時(shí)必須添加的參數(shù)
* @throws ServletException if any required properties are missing
*/
public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties)
throws ServletException {
Set<String> missingProps = (requiredProperties != null && !requiredProperties.isEmpty()) ?
new HashSet<String>(requiredProperties) : null;
Enumeration<String> en = config.getInitParameterNames();
while (en.hasMoreElements()) {
String property = en.nextElement();
Object value = config.getInitParameter(property);
addPropertyValue(new PropertyValue(property, value));
if (missingProps != null) {
missingProps.remove(property);
}
}
// Fail if we are still missing properties.
if (missingProps != null && missingProps.size() > 0) {
throw new ServletException(
"Initialization from ServletConfig for servlet '" + config.getServletName() +
"' failed; the following required properties were missing: " +
StringUtils.collectionToDelimitedString(missingProps, ", "));
}
}
}
}
這里只貼初始化的需要的部份代碼,根據(jù)上面的邏輯,子類實(shí)現(xiàn)了initServletBean()
這個(gè)方法進(jìn)行初始化
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
protected void initFrameworkServlet() throws ServletException {
}
//實(shí)現(xiàn)HttpServletBean 的初始化接口
@Override
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
}
long startTime = System.currentTimeMillis();
try {
//初始化webApplicationContext
this.webApplicationContext = initWebApplicationContext();
//這個(gè)是留給子類去實(shí)現(xiàn)的方法,暫時(shí)來(lái)講沒有具體的實(shí)現(xiàn),主要是留給開發(fā)人員自定義1些特性的時(shí)候
//這個(gè)時(shí)候WebApplicationContext已被初始化了,也就是1些個(gè)spring的配置文件已被初始化了
initFrameworkServlet();
}
catch (ServletException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
catch (RuntimeException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
if (this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
elapsedTime + " ms");
}
}
protected WebApplicationContext initWebApplicationContext() {
//獲得根的Context對(duì)象,比如說(shuō)我用了Spring boot或注解的方式進(jìn)行初始化,那末這里的Context就是Spring boot或其他的context對(duì)象
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
//如果當(dāng)前的webApplicationContext 不等于null
if (this.webApplicationContext != null) {
// A context instance was injected at construction time -> use it
wac = this.webApplicationContext;
//如果context對(duì)象是ConfigurableWebApplicationContext
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
//如果ConfigurableWebApplicationContext 不是存活狀態(tài)
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provide services such as
// setting the parent context, setting the application context id, etc
//如果沒有設(shè)置過(guò)parent
if (cwac.getParent() == null) {
// The context instance was injected without an explicit parent -> set
// the root application context (if any; may be null) as the parent
cwac.setParent(rootContext);
}
//
configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
// No context instance was injected at construction time -> see if one
// has been registered in the servlet context. If one exists, it is assumed
// that the parent context (if any) has already been set and that the
// user has performed any initialization such as setting the context id
//查詢當(dāng)前的Context,下述有詳細(xì)講授
wac = findWebApplicationContext();
}
//如果沒有找到那末就通過(guò)rootContext 去創(chuàng)建1個(gè)Context對(duì)象
if (wac == null) {
// No context instance is defined for this servlet -> create a local one
wac = createWebApplicationContext(rootContext);
}
//如果允許通過(guò)事件通知,那末就直接初始化。通過(guò)事件的通知可以反向的說(shuō)明onRefresh()這個(gè)方法是可以被重復(fù)調(diào)用的,具體分析看下面
if (!this.refreshEventReceived) {
// Either the context is not a ConfigurableApplicationContext with refresh
// support or the context injected at construction time had already been
// refreshed -> trigger initial onRefresh manually here.
onRefresh(wac);
}
// Publish the context as a servlet context attribute.
//如果允許publish Context的話那末就把spring context放入到spring的ServletContext中
if (this.publishContext) {
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
"' as ServletContext attribute with name [" + attrName + "]");
}
}
return wac;
}
//創(chuàng)建and refresh WebApplicationContext
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
//判斷id
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
if (this.contextId != null) {
wac.setId(this.contextId);
}
else {
// Generate default id...
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(getServletContext().getContextPath()) + "/" + getServletName());
}
}
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());
//添加針對(duì)ContextRefreshListener事件的監(jiān)聽
//ApplicationListener decorator that filters events from a specified event source, invoking its delegate listener for matching ApplicationEvent objects only.
//看了1下英文,大概是用了decorator(裝潢)模式,具體源碼里面,也只是做了1個(gè)簡(jiǎn)單的裝潢模式,這個(gè)類接受所有的ApplicationEvent事件
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
// The wac environment's #initPropertySources will be called in any case when the context
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
// use in any post-processing or initialization that occurs below prior to #refresh
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
}
//Post-process the given WebApplicationContext before it is refreshed
//大概就是說(shuō),在初始化handlermapping和1些本地化等調(diào)用refresh方法之前處理WebApplicationContext,這個(gè)類沒有具體實(shí)現(xiàn),開發(fā)者可以自己去處理
postProcessWebApplicationContext(wac);
//spring dispatcherServlet初始化的時(shí)候可以指定初始化1些類
applyInitializers(wac);
//這個(gè)是重點(diǎn)方法,這里采取了事件的模式進(jìn)行通知,去調(diào)用refresh方法初始化配置
wac.refresh();
}
//初始化spring context的時(shí)候 初始化1些指定需要初始化的類 這些類需要實(shí)現(xiàn)ApplicationContextInitializer 這個(gè)接口才能進(jìn)行調(diào)用
protected void applyInitializers(ConfigurableApplicationContext wac) {
//獲得到ServletContext中初始化的類數(shù)組參數(shù)
//
String globalClassNames = getServletContext().getInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM);
if (globalClassNames != null) {
//不斷的去初始化這個(gè)類數(shù)組 以,;\t\n等作為分隔符
for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {
this.contextInitializers.add(loadInitializer(className, wac));
}
}
if (this.contextInitializerClasses != null) {
for (String className : StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS)) {
this.contextInitializers.add(loadInitializer(className, wac));
}
}
//排序,可以指定這些類的初始化順序,通過(guò)@Order注解來(lái)實(shí)現(xiàn)排序
AnnotationAwareOrderComparator.sort(this.contextInitializers);
//初始化
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
initializer.initialize(wac);
}
}
//初始化類,
private ApplicationContextInitializer<ConfigurableApplicationContext> loadInitializer(
String className, ConfigurableApplicationContext wac) {
try {
//加載這個(gè)類
Class<?> initializerClass = ClassUtils.forName(className, wac.getClassLoader());
//判斷是不是實(shí)現(xiàn)了接口ApplicationContextInitializer
Class<?> initializerContextClass =
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
if (initializerContextClass != null && !initializerContextClass.isInstance(wac)) {
throw new ApplicationContextException(String.format(
"Could not apply context initializer [%s] since its generic parameter [%s] " +
"is not assignable from the type of application context used by this " +
"framework servlet: [%s]", initializerClass.getName(), initializerContextClass.getName(),
wac.getClass().getName()));
}
//初始化對(duì)象
return BeanUtils.instantiateClass(initializerClass, ApplicationContextInitializer.class);
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(String.format("Could not load class [%s] specified " +
"via 'contextInitializerClasses' init-param", className), ex);
}
}
}
上述代碼獲得root Context的時(shí)候可以通過(guò)以下代碼了解到獲得方式,webapp的Context對(duì)象的保存,其實(shí)不過(guò)就是把spring的context放到了ServletContext的1個(gè)屬性中而已
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
public abstract class WebApplicationContextUtils {
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
/**
* Find a custom {@code WebApplicationContext} for this web app.
* @param sc ServletContext to find the web application context for
* @param attrName the name of the ServletContext attribute to look for
* @return the desired WebApplicationContext for this web app, or {@code null} if none
*/
public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {
Assert.notNull(sc, "ServletContext must not be null");
//通過(guò)從ServletContext 去獲得spring的context對(duì)象
Object attr = sc.getAttribute(attrName);
if (attr == null) {
return null;
}
if (attr instanceof RuntimeException) {
throw (RuntimeException) attr;
}
if (attr instanceof Error) {
throw (Error) attr;
}
if (attr instanceof Exception) {
throw new IllegalStateException((Exception) attr);
}
if (!(attr instanceof WebApplicationContext)) {
throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr);
}
return (WebApplicationContext) attr;
}
}
wac = findWebApplicationContext();
上述這塊邏輯主要是通過(guò)獲得ContextAttribute的屬性名去ServletContext中獲得Context對(duì)象
protected WebApplicationContext findWebApplicationContext() {
String attrName = getContextAttribute();
if (attrName == null) {
return null;
}
WebApplicationContext wac =
WebApplicationContextUtils.getWebApplicationContext(getServletContext(), attrName);
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: initializer not registered?");
}
return wac;
}
這里流程比較繁瑣,重點(diǎn)講述1下 wac.refresh();
這個(gè)方法會(huì)調(diào)用AbstractApplicationContext
這里類面的refresh去實(shí)現(xiàn)相應(yīng)的邏輯,這個(gè)類具體的英文解釋(implements common context functionality. Uses the Template Method design pattern) 大概意思就是說(shuō)實(shí)現(xiàn)了1些公有的方法,通過(guò)Template Method這類設(shè)計(jì)模式實(shí)現(xiàn)功能,其實(shí)也就是將邏輯放到了AbstractApplicationContext
中,然后子類去實(shí)現(xiàn)各種方法。邏輯已由AbstractApplicationContext
定好,子類不關(guān)心邏輯
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
//準(zhǔn)備刷新之前調(diào)用
protected void prepareRefresh() {
//記錄開始時(shí)間
this.startupDate = System.currentTimeMillis();
//改變狀態(tài)
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
//這個(gè)主要留給子類去實(shí)現(xiàn)
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
//校驗(yàn)必須初始化的參數(shù)
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
//初始化1些beanFactory參數(shù)
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
//設(shè)置classLoader
beanFactory.setBeanClassLoader(getClassLoader());
//設(shè)置bean表達(dá)式解析器 spring 的el 表達(dá)式
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//使用資源編輯器來(lái)填充指定的PropertyEditorRegistry。
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//負(fù)責(zé)注入ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware ApplicationContext相干特性的Bean
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//This is intended for factory/context references that are supposed to be autowirable but are not defined as beans in the factory: e.g. a dependency of type ApplicationContext resolved to the ApplicationContext instance that the bean is living in.
//上述英文大概意思就是定義了1個(gè)特殊的bean,但是這個(gè)bean不通過(guò) beanFactory進(jìn)行管理生命周期,beanFactory本身就是1個(gè)bean,本身管理本身就有點(diǎn)奇怪,所以這個(gè)方法是注冊(cè)1些特殊的bean,并且可以進(jìn)行注入
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//preparecontext之前履行的操作
prepareRefresh();
//告知子類刷新bean工廠,spring boot能夠做到改變1個(gè)類進(jìn)行熱部署,我猜可能就調(diào)用了這個(gè)刷新方法去刷新bean工廠,所以改變了1些靜態(tài)變量spring boot是不會(huì)動(dòng)態(tài)刷新的
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//初始化1些bean工廠的參數(shù)
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 增加處理servletContext的類
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
//初始化消息源
// Initialize message source for this context.
initMessageSource();
//初始化消息事件
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
//發(fā)送refresh事件
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
}
AbstractApplicationContext
這個(gè)類比較繁瑣,這里只大概描寫了1下大概的功能,后續(xù)文章會(huì)詳細(xì)進(jìn)行講授,這里主要是講授初始化流程
.png?dir=0&filepath=spring%2FsourceCode%2Fimg%2Fdipatcher+%281%29.png&oid=d32d3920eb9fa1afe65c08f70e5e3c3966ddd8e2&sha=de3a2aaf492d9bcacf82f1462d06bd50f6091186)