死磕Spring系列,SpringBoot启动流程
参考文章:SpringBoot启动流程系列讲解
参考视频:SpringBoot启动流程
吐血推荐视频:史上最完整的Spring启动流程
超级好文:SpringBoot执行原理
参考文章:SpringBoot资源接口ResourceLoader和Resource学习
参考文章:到底什么是上下文(Context)
参考文章:超级好文
参考文章:这个系列的文章,让我自愧不如,痛删了原来2W字的内容
文章目录
- Spring Boot启动流程
-
- 服务构建
- 环境准备
- 容器创建
- 填充容器
- 非常重要的函数
-
- getSpringFactoriesInstances()
- getClassLoader()
- deduceMainApplicationClass()
- getRunListeners(String[] args)
- SpringApplicationRunListeners.starting()
- prepareEnvironment(SpringApplicationRunListeners, applicationArguments)
- prepareContext()
- refreshContext()
- refreshContext().refresh().obtainFreshBeanFactory()
- refreshContext().refresh().finishBeanFactoryInitialization(beanFactory)
- 非常重要的类
-
- ResourceLoader
- 总结
-
- 4. 填充容器(就是容器创建的refreshContext)
Spring Boot启动流程
服务构建
//SpringApplication类
//只列出几个重要的字段和方法
public class SpringApplication {//SpringApplication默认web容器类public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."+ "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";//banner名称,默认为banner.txtpublic static final String BANNER_LOCATION_PROPERTY_VALUE = SpringApplicationBannerPrinter.DEFAULT_BANNER_LOCATION;//banner位置key,默认为spring.banner.locationpublic static final String BANNER_LOCATION_PROPERTY = SpringApplicationBannerPrinter.BANNER_LOCATION_PROPERTY;//调用main函数的类,也就是YanggxApplication.classprivate Class<?> mainApplicationClass;//bean名称生成器,执行结果为nullprivate BeanNameGenerator beanNameGenerator;//spring的环境,我们使用的是ServletWeb环境private ConfigurableEnvironment environment;//web类型,执行结果为SERVLETprivate WebApplicationType webApplicationType;//Application初始化器,springboot启动过程中执行其initialize方法private List<ApplicationContextInitializer<?>> initializers;//Application监听器,springboot启动过程执行其onApplicationEvent方法private List<ApplicationListener<?>> listeners;/* SpringApplication构造函数* @param resourceLoader 资源加载器的策略接口,传参null,* @param primarySources 传参YanggxApplication.class*/public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {//执行结果:nullthis.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");//Set去重:"primarySources":[com.yanggx.spring.YanggxApplication.class]this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// 判断当前模块web类型:"webApplicationType":"SERVLET"this.webApplicationType = WebApplicationType.deduceFromClasspath();// 加载Application初始化器// 获取所有"META-INF/spring.factories"文件中维护的ApplicationContextInitializer子类列表// org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer// org.springframework.boot.context.ContextIdApplicationContextInitializer // org.springframework.boot.context.config.DelegatingApplicationContextInitializer // org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer // org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListenersetInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 3.3 加载Application监听器// 获取所有"META-INF/spring.factories"文件中维护的ApplicationListener子类列表// org.springframework.boot.ClearCachesApplicationListener// org.springframework.boot.builder.ParentContextCloserApplicationListener// org.springframework.boot.context.FileEncodingApplicationListener// org.springframework.boot.context.config.AnsiOutputApplicationListener// org.springframework.boot.context.config.ConfigFileApplicationListener// org.springframework.boot.context.config.DelegatingApplicationListener// org.springframework.boot.context.logging.ClasspathLoggingApplicationListener// org.springframework.boot.context.logging.LoggingApplicationListener// org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener// org.springframework.boot.autoconfigure.BackgroundPreinitializer// 加载的这些类都是ApplicationListener的子类setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 3.4 找到启动类// 抛出一个RuntimeException,然后通过堆栈信息找到启动类//"mainApplicationClass": com.yanggx.spring.YanggxApplication.classthis.mainApplicationClass = deduceMainApplicationClass();}
}
环境准备
public class SpringApplication {public ConfigurableApplicationContext run(String... args) {//实例化一个StopWatch实例, 监控项目运行时间StopWatch stopWatch = new StopWatch();stopWatch.start();//初始化Spring上下文ConfigurableApplicationContext context = null;//初始化错误报告参数Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();//配置headless,在没有显示器,鼠标,键盘的情况下,仍然可以调用显示,输入输出的方法configureHeadlessProperty();//1. 发布Spring启动事件SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {/*2. 这一步的主要作用是处理启动类main函数的参数, 将其封装为一个 DefaultApplicationArguments对象, 为prepareEnvironment()提供参数*/ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//3.这一步的主要作用按顺序加载命令行参数, 系统参数和外部配置文件, 创建并配置Web环境ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment);//4. 打印Banner图Banner printedBanner = printBanner(environment);//....}
容器创建
public ConfigurableApplicationContext run(String... args) {//步骤1: 根据switch创建context,分别有:SERVLET、REACTIVE、NONE,并且注册了Bean后置处理器context = createApplicationContext();//步骤2: BeanFactory是在这里创建的context.setApplicationStartup(this.applicationStartup);//步骤2: prepareContext()准备应用上下文prepareContext(context, environment, listeners, applicationArguments, printedBanner);//步骤3: refreshContext()刷新应用上下文,BeanDefinition和BeanFactory都是在这里创建的refreshContext(context);//步骤4: 刷新完成,该方法是拓展接口,用户可以自定义操作逻辑afterRefresh(context, applicationArguments);//步骤6: 发布Application开始事件listeners.started(context);//步骤7: 执行Runners,用于调用项目中自定义的执行器xxxRunner类,//在项目启动完成后立即执行,这些操作只在服务启动时执行一次callRunners(context, applicationArguments);//步骤8: 发布Application准备事件listeners.running(context);return context;
}
填充容器
/* 抽象父类ApplicationContext*/
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//刷新前操作,例如:清空缓存、初始化占位符prepareRefresh();//获取并刷新beanFactory,创建BeanFactory和BeanDefinitionConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//设置beanFactory,配置各种beanFactory.xxx属性prepareBeanFactory(beanFactory);//beanFactory的后置处理器:注册与Servlet相关的特殊Bean,注册beanDefinitionpostProcessBeanFactory(beanFactory);/*BeanFactoryPostProcessor是一个接口, 处理beanFactory中所有的bean, 在所有的beanDefinition加载完成之后, BeanFactoryPostProcessor可以对beanDefinition进行属性的修改, 之后再进行bean实例化*/invokeBeanFactoryPostProcessors(beanFactory);//beanFactory注册后置处理器,对bean实例的增强registerBeanPostProcessors(beanFactory);//初始化messageSourceinitMessageSource();//初始化Application事件发布器initApplicationEventMulticaster();//初始化其他特殊的bean,例如实例化了TomcatWebServeronRefresh();//注册监听器registerListeners();//完成beanFactory初始化finishBeanFactoryInitialization(beanFactory);//完成刷新,发布完成事件,实例化了所有beanfinishRefresh(); }
}
非常重要的函数
getSpringFactoriesInstances()
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = this.getClassLoader();Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {//主要获取spring.factories中的key,key对应接口全名String factoryTypeName = factoryType.getName();//筛选Map中key为factoryTypeName对应放到list返回 return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}
//会把Spring.factories文件中所有键值对放到Map中,其实就是缓存//classLoader参数就是"META-INF/spring.factories"加载器private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {//如果缓存已经有Spring.factories,那就从缓存中拿MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}//如果缓存中没有Spring.factories,那就从重新加载到缓存Enumeration<URL> urls = (classLoader != null ?// FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories" classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;}
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,ClassLoader classLoader, Object[] args, Set<String> names) {List<T> instances = new ArrayList<>(names.size());for (String name : names) {try {//通过反射机制创建实例Class<?> instanceClass = ClassUtils.forName(name, classLoader);Assert.isAssignable(type, instanceClass);Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);T instance = (T) BeanUtils.instantiateClass(constructor, args);instances.add(instance);}catch (Throwable ex) {throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);}}return instances;}
总结:
- loadSpringFactories(@Nullable ClassLoader classLoader):判断缓存是否有Spring.factories文件,如果有就提取整个spring.factories。如果没有就加载到缓存再提取。
- loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader):从spring.factories文件中获取指定factoryType
- createSpringFactoriesInstances(Class type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set names):将loadFactoryNames()返回的factoryType,通过反射机制实例化- getSpringFactoriesInstances(Class type, Class<?>[] parameterTypes, Object… args):获取createSpringFactoriesInstances()返回的实例instances,返回实例
getClassLoader()
- 我们都知道java程序写好以后是以.java(文本文件)的文件存在磁盘上,然后,我们通过(bin/javac.exe)编译命令把.java文件编译成.class文件(字节码文件),并存在磁盘上。
但是程序要运行,首先一定要把.class文件加载到JVM内存中才能使用的,我们所讲的classLoader,就是负责把磁盘上的.class文件加载到JVM内存中- 你可以认为每一个Class对象拥有磁盘上的那个.class字节码内容,每一个class对象都有一个getClassLoader()方法,得到是谁把我从.class文件加载到内存中变成Class对象的
deduceMainApplicationClass()
private Class<?> deduceMainApplicationClass() {try {//通过一个RuntimeException,获取器堆栈信息StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())) {//堆栈中包含main方法,实例化一个该类的对象return Class.forName(stackTraceElement.getClassName());}}}catch (ClassNotFoundException ex) { }return null;
}
getRunListeners(String[] args)
//当前只能获取SpringApplicationRunListener子类列表EventPublishingRunListenerprivate SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}
SpringApplicationRunListeners.starting()
//该SpringApplicationRunListeners存在多个子类,在下面starting方法中,会调用对应子类的starting方法
class SpringApplicationRunListeners {//发布启动事件public void starting() {for (SpringApplicationRunListener listener : this.listeners) {//目前调用EventPublishingRunListener的starting方法listener.starting();}}//其他事件都是相同的代码
}
//不仅仅是ApplicationListeners存在很多子类,EventPublishingRunListener也有很多子类
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {//SpringApplication对象private final SpringApplication application;//命令函参数private final String[] args;//事件广播器private final SimpleApplicationEventMulticaster initialMulticaster;public EventPublishingRunListener(SpringApplication application, String[] args) {this.application = application;this.args = args;this.initialMulticaster = new SimpleApplicationEventMulticaster();// 通过application.getListeners(),获取到Listener列表// ConfigFileApplicationListener// AnsiOutputApplicationListener// LoggingApplicationListener// ClasspathLoggingApplicationListener// BackgroundPreinitializer// DelegatingApplicationListener// ParentContextCloserApplicationListener// ClearCachesApplicationListener// FileEncodingApplicationListener// LiquibaseServiceLocatorApplicationListenerfor (ApplicationListener<?> listener : application.getListeners()) {//将listener添加到事件广播器initialMulticasterthis.initialMulticaster.addApplicationListener(listener);}}@Overridepublic void starting() {// 广播器广播ApplicationStartingEvent事件this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));}//其他事件发布都是相同的代码//...
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));//调用父类getApplicationListeners方法//遍历所有支持ApplicationStartingEvent事件的监听器//LoggingApplicationListener//BackgroundPreinitializer//DelegatingApplicationListener//LiquibaseServiceLocatorApplicationListenerfor (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {//此时的executor为nullExecutor executor = getTaskExecutor();if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {//调用listenerinvokeListener(listener, event);}}}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = this.getErrorHandler();if (errorHandler != null) {try {this.doInvokeListener(listener, event);} catch (Throwable var5) {errorHandler.handleError(var5);}} else {this.doInvokeListener(listener, event);}}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {//调用listener的onApplicationEvent方法listener.onApplicationEvent(event);}
onApplicationEvent(event){到这里就不再深究了,这个方法有三十个实现类,操作基本上就是绑定环境,设置参数等等
}
总结:
- SpringApplicationRunListeners.starting()调用了EventPublishingRunListener.starting();
- EventPublishingRunListener.starting()调用了广播器initialMulticaster.multicastEvent()发布SpringApplication启动事件
- initialMulticaster.multicastEvent()分别调用了LoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、LiquibaseServiceLocatorApplicationListener的invokeListener()方法
invokeListener()——doInvokeListener()——onApplicationEvent()——设置参数、绑定环境等等
prepareEnvironment(SpringApplicationRunListeners, applicationArguments)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {//获取或者创建环境,根据switch判断,选择SERVLET、REACTIVE、NONE类型ConfigurableEnvironment environment = getOrCreateEnvironment();//配置环境:为environment配置“共享的类型转换服务”,即:A数据类型变成B数据类型 //然后将defaultProperties和args分别添加到environment的propertySources中configureEnvironment(environment, applicationArguments.getSourceArgs());//发布环境准备事件listeners.environmentPrepared(environment);//如果指定了main函数,那么会将当前环境绑定到指定的SpringApplication中bindToSpringApplication(environment);if (!this.isCustomEnvironment) {//环境转换:如果environment.class和模块EnvironmentClass()不一致,就转换成一样的environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());}//将环境依附到PropertySourcesConfigurationPropertySources.attach(environment);return environment;}
prepareContext()
private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {//设置context环境:统一ApplicationContext与Application.environment一致context.setEnvironment(environment);//设置ApplicationContext.beanNameGenerator、resourceLoader、classLoader、类型转换服务postProcessApplicationContext(context);//获取6个初始化器并执行初始化方法,例如设置元数据、配置警告、获取应用名称applyInitializers(context);//发布contextPrepared事件listeners.contextPrepared(context);if (this.logStartupInfo) {//配置了info日志//打印启动和profile日志logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}//获取到DefaultListableBeanFactory实例ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();//注册名为springApplicationArguments,值为applicationArguments的单例beanbeanFactory.registerSingleton("springApplicationArguments", applicationArguments);//banner不为空,那么注册名为springBootBanner,值为printedBanner的单例beanif (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {//allowBeanDefinitionOverriding默认为false((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// 获取sources列表,获取到我们的YanggxApplication.classSet<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");//初始化bean加载器,并加载bean到应用上下文load(context, sources.toArray(new Object[0]));//发布contextLoaded事件listeners.contextLoaded(context);}
refreshContext()
//刷新应用上下文,注册关闭应用钩子private void refreshContext(ConfigurableApplicationContext context) {refresh(context);if (this.registerShutdownHook) context.registerShutdownHook();}
/* 抽象父类ApplicationContext*/
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//清空缓存、清空监听器、判断必要属性是否被忽略、打印日志、初始化占位符、设置earlyApplicationEventsprepareRefresh();//获取并刷新beanFactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();/*配置classLoader为当前context的classLoader设置BeanExpressionResolver, 解析EL表达式设置属性编辑器添加BeanPostProcessor配置自动装配手工注册environment相关bean*/prepareBeanFactory(beanFactory);/*注册basepackages注册annotatedClasses注册了request和session两个scopes注册几个Autowired依赖类 */postProcessBeanFactory(beanFactory);/*BeanFactoryPostProcessor接口用于增强BeanFactory,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取bean 的定义,并可以修改它。例如:public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) */invokeBeanFactoryPostProcessors(beanFactory);//beanFactory注册后置处理器,对bean实例的增强registerBeanPostProcessors(beanFactory);//初始化messageSourceinitMessageSource();//初始化Application事件发布器initApplicationEventMulticaster();//初始化其他特殊的bean,例如实例化了TomcatWebServeronRefresh();//注册监听器registerListeners();//完成beanFactory初始化finishBeanFactoryInitialization(beanFactory);//完成刷新,发布完成事件,实例化了所有beanfinishRefresh();} }
}
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {protected void prepareRefresh() {//记录开始时间,调整active状态this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);//初始化占位符,例如:$,#,{}initPropertySources();//如果属性中缺少requiredProperties,那么抛出MissingRequiredPropertiesExceptiongetEnvironment().validateRequiredProperties();//清空监听器if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);}else {this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}//初始化earlyApplicationEventsthis.earlyApplicationEvents = new LinkedHashSet<>();}
}
refreshContext().refresh().obtainFreshBeanFactory()
/*refreshBeanFactory():创建beanFactory、指定序列化Id、定制beanFactory、加载bean定义getBeanFactory():返回beanFactory实例
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {//1.初始化beanFactory,并执行加载和解析配置操作refreshBeanFactory();//返回beanFactory实例ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (logger.isDebugEnabled()) {logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);}return beanFactory;}
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {... @Overrideprotected final void refreshBeanFactory() throws BeansException {//判断是否存在beanFactoryif (hasBeanFactory()) {// 注销所有的单例destroyBeans();//重置beanFactorycloseBeanFactory();}try {//创建beanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();//指定序列化id,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象beanFactory.setSerializationId(getId());//定制BeanFactorycustomizeBeanFactory(beanFactory);//下载BeanDefinitions,放到BeanDefinitionsMaploadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}}...
}
refreshContext().refresh().finishBeanFactoryInitialization(beanFactory)
/* 根据loadBeanDefinitions加载的BeanDinition到BeanDefinitionMap,再从BeanDefinitionMap拿出来BeanDefinitionMap创建Bean
*/
createBean(){//1. createBeanInstance通过反射机制获取Bean的构造方法,然后创建Bean。当然,如果构造方法需要参数,就会到单例池中查找。//2. populateBean填充Bean属性//3. 初始化1. 初始化容器信息,通过invokeAwareMethods(),唤醒各种Aware接口,获取Bean在容器中的信息2. 初始化Bean成普通对象:通过invokeInitMethods(),执行Bean的初始化方法,这个方法可以通过实现InitialzingBean接口实现的afterPropertiesSet方法。3. AOP操作Bean成:初始化之前和之后处理各种Bean的后置处理器,即在invokeInitMethods()之前和之后分别执行applyBeanPostProcessorsBeforeInitialization()和applyBeanPostProcessorsAfterInitialization()//4. 注册销毁实现了销毁接口DisposableBean,在registerDisposableBean方法注册指定的Bean在销毁时可以直接执行destroy方法销毁Bean
}addSingleton(){将上面create出来的Bean放入单例池就可以获取和使用了
}
非常重要的类
ResourceLoader
//默认的资源加载器
public class DefaultResourceLoader implements ResourceLoader {@Nullableprivate ClassLoader classLoader;//自定义ProtocolResolver, 用于获取资源private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);//private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);//实例化ClassLoaderpublic DefaultResourceLoader() {this.classLoader = ClassUtils.getDefaultClassLoader();}//加载资源@Overridepublic Resource getResource(String location) {Assert.notNull(location, "Location must not be null");//自定义资源加载方式for (ProtocolResolver protocolResolver : this.protocolResolvers) {//调用ProtocolResolver的resolve方法Resource resource = protocolResolver.resolve(location, this);if (resource != null) {//如果获取到资源,立即返回return resource;}}if (location.startsWith("/")) {//先判断是否是根目录return getResourceByPath(location);}else if (location.startsWith(CLASSPATH_URL_PREFIX)) {//再判断是否是classpath下的资源return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());}else {try {//先当做一个URL处理URL url = new URL(location);//先判断是否是一个file//不是file的话,再从URL中获取return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));}catch (MalformedURLException ex) {//获取不到资源的话//当做resource处理return getResourceByPath(location);}}}
}
总结
1. 服务构建
- 设置primarySources:YanggxApplication.class
- 设置webType:SERVLET
- 从Spring.factories获取初始化器
- 从Spring.factories获取监听器ApplicationListener
- 设置启动类:YanggxApplication.class
2. 环境准备
- 发布Spring启动事件listeners.starting()
- 封装args参数 new DefaultApplicationArguments(args);
- 配置环境并让环境生效prepareEnvironment() & configureIgnoreBeanInfo()
- 打印Banner图printBanner(environment)
3. 容器创建
- 创建容器createApplicationContext()
- 设置容器prepareContext()
- 刷新容器refreshContext(),这里也是填充容器,重点是 invokeBeanFactoryPostProcessors(beanFactory);和onRefresh()
- 执行Runners
4. 填充容器(就是容器创建的refreshContext)