1.看源码的入口
public static void main(String[] args) {
SpringApplication.run(MerchantSignApplication.class, args);
}//任何一个application启动类,都可以找到这个地方
2.第一个比较重要的地方
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args){
.......
}
看方法上面注释可以知道,这个类的作用是运行spring应用程序,创建和刷新上下文内容,传入的参数类似main方法,启动的时候配置,返回一个正在运行的上下文;
主要做的工作:
(1).创建定时器并且启动
(2).配置java.awt.headless模式(在该模式下,系统缺少了显示设备、键盘或鼠标)
(3).获取运行的spring监听器,主要是配置在spring.factories然后key为SpringApplicationRunListener的类
(4).启动这些监听器
(5).准备环境
(6).banner打印
(7).创建web上下文或者默认上下文
(8).利用上下文创建分析类
(9).预备上下文环境
(10).刷新上下文
(11).后置上下文刷新
(12).关闭监听器
(13).停止定时器
(14).判断启动信息是否开,开的话就打印启动信息
3.解析各个步骤的实现细节
(1).仅仅是进行开始计时的操作,供最后打印启动信息时,打印出整个系统的启动时间使用
(2).配置成java.awt.headless模式,因为我们的程序会在服务器上跑,然后服务器是没有显示器也没有鼠标,这个模式就是为了让我们可以像有鼠标和显示器一样的操作
(3).
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
//获取类加载器
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<String>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));//核心方法一
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
//核心方法二
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
//获取所有jar下面的META-INF/spring.factories
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
//获取所有在spring.factories里面配置的类名为SpringApplicationRunListener对应的类
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
//通过反射创建出所有SpringApplicationRunListener类型的类
private <T> List<T> createSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
Set<String> names) {
List<T> instances = new ArrayList<T>(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;
}
(4).启动监听器
@Override
@SuppressWarnings("deprecation")
public void starting() {
//创建应用启动事件,然后设置它们
this.initialMulticaster
.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {//通过事件和类型获取所有的应用监听器,为所有的监听器注册事件
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
(5).获取配置环境
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();//获取或者创建环境对象
configureEnvironment(environment, applicationArguments.getSourceArgs());//这里是对启动时传入的参数做处理,以及激活的配置文件和多个配置属性源数据加入
listeners.environmentPrepared(environment);//为所有的监听器准备环境变量,同时也包装成事件进行注册
if (!this.webEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertToStandardEnvironmentIfNecessary(environment);//将环境变为web环境
}
return environment;
}
(6).banner打印,这里的功能就是每次启动boot应用时前面会打印的那个图案
" . ____ _ __ _ _",
" /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\",
"( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\",
" \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )",
" ' |____| .__|_| |_|_| |_\\__, | / / / /",
" =========|_|==============|___/=/_/_/_/"
private Banner printBanner(ConfigurableEnvironment environment) {
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
ResourceLoader resourceLoader = (this.resourceLoader != null ? this.resourceLoader
: new DefaultResourceLoader(getClassLoader()));
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(
resourceLoader, this.banner);
if (this.bannerMode == Mode.LOG) {
return bannerPrinter.print(environment, this.mainApplicationClass, logger);
}
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
(7).创建web上下文或者默认上下文,这个看下代码就知道了很简单,通过反射的方式创建出上下文
/**
* Strategy method used to create the {@link ApplicationContext}. By default this
* method will respect any explicitly set application context or application context
* class before falling back to a suitable default.
* @return the application context (not yet refreshed)
* @see #setApplicationContextClass(Class)
*/
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
(8).利用上下文创建分析类,将上一步创建出的上下文作为参数直接创建出该类,用于分析故障并提供可以显示给用户的诊断信息
analyzers = new FailureAnalyzers(context);
(9).预备上下文环境,将上面创建出来的对象都设置到创建出的上下文应用中
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);//为上下问设置外部环境
postProcessApplicationContext(context);//进入这个方法里面的
applyInitializers(context);//初始化给定的应用程序上下文
listeners.contextPrepared(context);//在上下文创建和准备之后调用,但是在资源加载之前使用
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);//看注释就知道是注册boot特别的bean
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);//如果有banner就需要注册springBootBanner bean
}
// Load the sources
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[sources.size()]));//将资源文件中的bean加载到上下文中
listeners.contextLoaded(context);//主要就是注册事件,供之前的listener监听到
}
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
..........
}
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
//这里主要就是对循环依赖做处理,
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames.size() + 1);
updatedSingletons.addAll(this.manualSingletonNames);
updatedSingletons.add(beanName);
this.manualSingletonNames = updatedSingletons;//这里就是先将集合中的bean拿出来然后放到新集合,再将新的bean设置进去,然后再将集合赋值给原来的
}
}
}
else {
// Still in startup registration phase
if (!this.beanDefinitionMap.containsKey(beanName)) {
this.manualSingletonNames.add(beanName);//添加到手动注册单例bean的集合
}
}
clearByTypeCache();//清空以类型为间的集合
}
/**
* Load beans into the application context.
* @param context the context to load beans into
* @param sources the sources to load
*/
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();//加载source
}
(10).刷新上下文
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();//注册关闭虚拟机的钩子方法,可以多次调用此方法。每个上下文实例仅注册一个关闭钩子
}
.....
}
//这个是核心方法
@Override
public void refresh() throws BeansException, IllegalStateException {
//刷新和关闭时候的监控对象
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing. 准备此上下文以进行刷新
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//配置一些beanFactory的信息,例如ClassLoader和后处理器,还有一些必要的bean添加到工厂,一些需要忽视依赖注入的bean配置
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
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);
// 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();
}
}
}
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
//设置启动时间以及一些标志位
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment,初始化配置文件中的占位符,替换实际的值
initPropertySources();
// Validate that all properties marked as required are resolvable
// see 验证一些必须的属性在ConfigurablePropertyResolver#setRequiredProperties 设置的
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
//用于收集应用的相关事件
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();//前置操作对beanFactory做初始化,设置beanNameGenerate等
ConfigurableListableBeanFactory beanFactory = getBeanFactory();//获取到上一步初始化后的beanFactory
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
网友评论