直接从启动类开始说起,springboot的入口就是 在main启动类的
SpringApplication.run方法,这是Application的一个静态方法,那么要执行这个静态方法,肯定首先要对SpringApplication进行初始化,该类初始化的方法如下,前面几步都是给变量赋值,没什么好说的,主要看最后一步:initialize();
public static void main(String[] args) { SpringApplication.run(Demo22Application.class, args); }
---->
public SpringApplication(ResourceLoader resourceLoader, Object... sources) { this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = new HashSet(); this.resourceLoader = resourceLoader; //上面几步都是对SpringApplication中的的几个变量进行赋值 主要看下下面这个方法 this.initialize(sources); } ----------> private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } // 判断是否是web程序(javax.servlet.Servlet和org.springframework.web.context.ConfigurableWebApplicationContext都必须在类加载器中存在),并设置到webEnvironment属性中 this.webEnvironment = this.deduceWebEnvironment(); ------> private boolean deduceWebEnvironment() { String[] var1 = WEB_ENVIRONMENT_CLASSES;//这个变量就是javax.servlet.Servlet和//org.springframework.web.context.ConfigurableWebApplicationContext int var2 = var1.length; for(int var3 = 0; var3 < var2; ++var3) { String className = var1[var3]; if (!ClassUtils.isPresent(className, (ClassLoader)null)) { return false; } } return true; }
<---------
// 从spring.factories文件中找出key为ApplicationContextInitializer的类并实例化后设置到SpringApplication的initializers属性中。这个过程也就是找出所有的应用程序初始化器
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
进入这个方法看一下
这个方法首先调用了getSpringFactoriesInstances方法,这个方法调用了重载方法
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); //看这里 Setnames = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); ----> loadFactoryNames z这个方法会找到类路径下jar包中的META-INF/spring.factories下所有的文件中以org.springframework.context.ApplicationContextInitializer为key的value 比如我们看spring-boot-1.4.7.relase下的 ----省略-- # Run Listeners org.springframework.boot.SpringApplicationRunListener=\ org.springframework.boot.context.event.EventPublishingRunListener # Application Context Initializers #这个文件下以org.springframework.context.ApplicationContextInitializer为key的value又四个 org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\ org.springframework.boot.context.ContextIdApplicationContextInitializer,\ org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\ org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer # Application Listeners org.springframework.context.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.liquibase.LiquibaseServiceLocatorApplicationListener,\ org.springframework.boot.logging.ClasspathLoggingApplicationListener,\ org.springframework.boot.logging.LoggingApplicationListener ---省略----
由于这个方法传入的clazz是ApplicationContextInitializer.class,最终找到的result=6
String factoryClassName = factoryClass.getName(); try { Enumerationurls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); ArrayList result = new ArrayList(); while(urls.hasMoreElements()) { URL 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 var8) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8); } } <--------- 初始化这几个类 List instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); 排序 AnnotationAwareOrderComparator.sort(instances); return instances;
----->
然后进入setInitializers方法,会发现是吧上一步初始化的集合赋值给SpringApplication中的initializers
public void setInitializers(Collection extends ApplicationContextInitializer>> initializers) { this.initializers = new ArrayList(); this.initializers.addAll(initializers); }
接着initialize方法
<-------
这个方法和上面的this.setInitializers方法类似,这个方法最终把SpringApplication上的listeners设置上值,
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 找出main类,这里是启动类 this.mainApplicationClass = this.deduceMainApplicationClass()
以上吧initialize 的全过程