第一章 springboot源码解析之SpringApplication初始化、启动

Springboot 源码分析环境搭建部分
step 1:下载源码 spring.io 选择 springboot 点击github下载1.5.x源码
step 2 : 配置jdk 1.8 、maven
step 3: mvn clean install -DskipTests -Pfast //跳过测试用例

SpringApplication初始化、启动

org.springframework.boot.SpringApplication#SpringApplication(java.lang.Object…) 这个类就是SpringApplication的构造方法。初始化工作

/**
	 * Create a new {@link SpringApplication} instance. The application context will load
	 * beans from the specified sources (see {@link SpringApplication class-level}
	 * documentation for details. The instance can be customized before calling
	 * {@link #run(String...)}.
	 * @param sources the bean sources
	 * @see #run(Object, String[])
	 * @see #SpringApplication(ResourceLoader, Object...)
	 */
	//第一步: springboot 容器的加载
	// ./mvnw clean install -DskipTests -Pfast //跳过测试用例
	public SpringApplication(Object... sources) {
		initialize(sources);
	}

org.springframework.boot.SpringApplication#initialize

// 第二步: 初始化 initialize
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void initialize(Object[] sources) {
		if (sources != null && sources.length > 0) {
			this.sources.addAll(Arrays.asList(sources));
		}
		// 第一步: 设置环境
		this.webEnvironment = deduceWebEnvironment();
		// 第二步: 获取ApplicationContextInitializer,也是在这里开始首次加载spring.factories文件
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		// 第三步: 获取监听器,这里是第二次加载spring.factories文件
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class)该类就是读取
META-INF/spring.factories文件

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer

进入到这个方法org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class)从META-INF/spring.factories路径加载

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
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

org.springframework.boot.SpringApplication#deduceMainApplicationClass 找到主类创建对象

private Class deduceMainApplicationClass() {
		try {
			StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
			for (StackTraceElement stackTraceElement : stackTrace) {
				if ("main".equals(stackTraceElement.getMethodName())) {
					return Class.forName(stackTraceElement.getClassName());
				}
			}
		}
		catch (ClassNotFoundException ex) {
			// Swallow and continue
		}
		return null;
	}

org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class) 获取工厂实例对象

private  Collection getSpringFactoriesInstances(Class type) {
		return getSpringFactoriesInstances(type, new Class[] {});
	}
private  Collection getSpringFactoriesInstances(Class type, Class[] parameterTypes,
			Object... args) {
		//获取当前类的类加载器
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		// Use names and ensure unique to protect against duplicates
		Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames 通过类名加载类

  public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) {
    String factoryClassName = factoryClass.getName();
    try {
      Enumeration urls = 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 propertyValue = properties.getProperty(factoryClassName);
        //分割、将多个类之间分割开来成一个一个的类路径
        String[] var8 = StringUtils.commaDelimitedListToStringArray(propertyValue);
        int var9 = var8.length;
        // 添加到容器中
        for(int var10 = 0; var10 < var9; ++var10) {
          String factoryName = var8[var10];
          result.add(factoryName.trim());
        }
      }

      return result;
    } catch (IOException var12) {
      throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var12);
    }
  }

前面是读取,既然读取了文件,肯定接下来就是创建对象。
org.springframework.boot.SpringApplication#createSpringFactoriesInstances 创建实例对象
这个类比较简单,就是基于反射创建对象

private  List createSpringFactoriesInstances(Class type, Class[] parameterTypes,
			ClassLoader classLoader, Object[] args, Set names) {
		List 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;
	}

介绍run方法
org.springframework.context.ConfigurableApplicationContext

	/**
	 * Static helper that can be used to run a {@link SpringApplication} from the
	 * specified source using default settings.
	 * @param source the source to load
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return the running {@link ApplicationContext}
	 */
	public static ConfigurableApplicationContext run(Object source, String... args) {
		return run(new Object[] { source }, args);
	}

org.springframework.context.ConfigurableApplicationContext

/**
	 * Static helper that can be used to run a {@link SpringApplication} from the
	 * specified sources using default settings and user supplied arguments.
	 * @param sources the sources to load
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return the running {@link ApplicationContext}
	 */
	public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
		return new SpringApplication(sources).run(args);
	}

前面介绍的是如何加载配置文件,后面介绍如和启动

public ConfigurableApplicationContext run(String... args) {
		// 第一步: 时间监控 设置启动时间
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		// 第二步: 该类可以获取到bean的相关配置
		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;
		// 第三步: 是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,
		// 很多监控工具如jconsole 需要将该值设置为true,系统变量默认为true
		configureHeadlessProperty();
		// 第四步: 获取并启动监听器
		//EventPublishingRunListener 比添加到对应的runner
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {

			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 第五步: 构造容器环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			// 第六步: 打印banner
			Banner printedBanner = printBanner(environment);
			// 第七步:创建容器
			context = createApplicationContext();
			// 第八步: 实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
			analyzers = new FailureAnalyzers(context);
			//第五步:准备容器
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			//第六步:刷新容器
			refreshContext(context);
			//第七步:刷新容器后的扩展接口
			afterRefresh(context, applicationArguments);
			listeners.finished(context, null);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			return context;
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, analyzers, ex);
			throw new IllegalStateException(ex);
		}
	}

获取并启动监听器 前面已经介绍过该类。

SpringApplicationRunListeners listeners = getRunListeners(args);
public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
	}

org.springframework.boot.SpringApplication#createApplicationContext 创建容器

/**
	 * 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 {
			//          创建基于annotation的上下文对象
				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);
	}

org.springframework.boot.SpringApplication#prepareContext 预处理上下文对象

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);
		if (printedBanner != null) {
			context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
		}

		// Load the sources
		Set sources = getSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		//    加载bean定义 =》
		load(context, sources.toArray(new Object[sources.size()]));
		//    执行spring上线文加载完成事件 -》
		listeners.contextLoaded(context);
	}
 
  

org.springframework.boot.SpringApplication#postProcessApplicationContext 后置处理器

/**
	 * Apply any relevant post processing the {@link ApplicationContext}. Subclasses can
	 * apply additional processing as required.
	 * @param context the application context
	 */
	protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
		if (this.beanNameGenerator != null) {
			context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
					this.beanNameGenerator);
		}
		// 获取资源加载器对象
		if (this.resourceLoader != null) {
			if (context instanceof GenericApplicationContext) {
			//如果是该类   GenericApplicationContext
				((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
			}
				//如果是该类   DefaultResourceLoader
			if (context instanceof DefaultResourceLoader) {
				((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
			}
		}
	}

org.springframework.boot.SpringApplication#applyInitializers 执行初始化器

/**
	 * Apply any {@link ApplicationContextInitializer}s to the context before it is
	 * refreshed.
	 * @param context the configured ApplicationContext (not refreshed yet)
	 * @see ConfigurableApplicationContext#refresh()
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	protected void applyInitializers(ConfigurableApplicationContext context) {
	//获取到springboot上下文初始化对象
		for (ApplicationContextInitializer initializer : getInitializers()) {
			Class requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
					ApplicationContextInitializer.class);
			Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
			// 初始化
			initializer.initialize(context);
		}
	}

添加到ConfigurableApplicationContext 容器中。
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer#initialize

@Override
	public void initialize(ConfigurableApplicationContext context) {
		context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
	}

//bean 的生命周期钩子
org.springframework.context.support.AbstractApplicationContext#addBeanFactoryPostProcessor

 public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
    Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
    this.beanFactoryPostProcessors.add(postProcessor);
  }

检查
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer#getChecks

/**
	 * Returns the checks that should be applied.
	 * @return the checks to apply
	 */
	protected Check[] getChecks() {
		return new Check[] { new ComponentScanPackageCheck() };
	}

// 扫面包对象
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ComponentScanPackageCheck

// 静态初始化对象
static {
			Set packages = new HashSet();
			packages.add("org.springframework");
			packages.add("org");
			PROBLEM_PACKAGES = Collections.unmodifiableSet(packages);
		}

springboot启动的时候组件扫描器会默认扫描这两个包


	@Override
	public void initialize(ConfigurableApplicationContext context) {
		ConfigurableEnvironment environment = context.getEnvironment();
		List> initializerClasses = getInitializerClasses(environment);
		if (!initializerClasses.isEmpty()) {
			applyInitializerClasses(context, initializerClasses);
		}
	}
private List> getInitializerClasses(ConfigurableEnvironment env) {
		String classNames = env.getProperty(PROPERTY_NAME);
		List> classes = new ArrayList>();
		if (StringUtils.hasLength(classNames)) {
			for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
				classes.add(getInitializerClass(className));
			}
		}
		return classes;
	}

默认初始化化类对象
org.springframework.boot.context.config.DelegatingApplicationContextInitializer#applyInitializerClasses

private void applyInitializerClasses(ConfigurableApplicationContext context, List> initializerClasses) {
		Class contextClass = context.getClass();
		List> initializers = new ArrayList>();
		for (Class initializerClass : initializerClasses) {
			initializers.add(instantiateInitializer(contextClass, initializerClass));
		}
		applyInitializers(context, initializers);
	}

org.springframework.boot.context.config.DelegatingApplicationContextInitializer#applyInitializers

private void applyInitializers(ConfigurableApplicationContext context,
			List> initializers) {
		Collections.sort(initializers, new AnnotationAwareOrderComparator());
		for (ApplicationContextInitializer initializer : initializers) {
			initializer.initialize(context);
		}
	}

listeners.contextPrepared(context);
org.springframework.boot.SpringApplicationRunListeners#contextPrepared

public void contextPrepared(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {、
		  // 添加到listener中
			listener.contextPrepared(context);
		}
	}
load(context, sources.toArray(new Object[sources.size()]));
/**
	 * 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();
	}

org.springframework.boot.BeanDefinitionLoader#load(java.lang.Object)

private int load(Object source) {
		Assert.notNull(source, "Source must not be null");
		if (source instanceof Class) {
			return load((Class) source);
		}
		if (source instanceof Resource) {
			return load((Resource) source);
		}
		if (source instanceof Package) {
			return load((Package) source);
		}
		if (source instanceof CharSequence) {
			return load((CharSequence) source);
		}
		throw new IllegalArgumentException("Invalid source type " + source.getClass());
	}

org.springframework.boot.SpringApplication#afterRefresh

afterRefresh(context, applicationArguments);
/**
	 * Called after the context has been refreshed.
	 * @param context the application context
	 * @param args the application arguments
	 */
	protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
		callRunners(context, args);
	}
private void callRunners(ApplicationContext context, ApplicationArguments args) {
		List runners = new ArrayList();
		runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
		runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
		AnnotationAwareOrderComparator.sort(runners);
		for (Object runner : new LinkedHashSet(runners)) {
			if (runner instanceof ApplicationRunner) {
				callRunner((ApplicationRunner) runner, args);
			}
			if (runner instanceof CommandLineRunner) {
				callRunner((CommandLineRunner) runner, args);
			}
		}
	}
 
  
/**
 * Interface used to indicate that a bean should run when it is contained within
 * a {@link SpringApplication}. Multiple {@link ApplicationRunner} beans can be defined
 * within the same application context and can be ordered using the {@link Ordered}
 * interface or {@link Order @Order} annotation.
 *
 * @author Phillip Webb
 * @since 1.3.0
 * @see CommandLineRunner
 */
public interface ApplicationRunner {

	/**
	 * Callback used to run the bean.
	 * @param args incoming application arguments
	 * @throws Exception on error
	 */
	void run(ApplicationArguments args) throws Exception;

}

org.springframework.boot.SpringApplicationRunListeners#finished

listeners.finished(context, null);
private void callFinishedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context,
			Throwable exception) {
		try {
			listener.finished(context, exception);
		}
		catch (Throwable ex) {
			if (exception == null) {
				ReflectionUtils.rethrowRuntimeException(ex);
			}
			if (this.log.isDebugEnabled()) {
				this.log.error("Error handling failed", ex);
			}
			else {
				String message = ex.getMessage();
				message = (message != null) ? message : "no error message";
				this.log.warn("Error handling failed (" + message + ")");
			}
		}
	}

执行监听器的spring上下文加载完毕事件

你可能感兴趣的:(springboot源码分析,springboot,源码装配过程)