Spring框架探索一 (springboot配置环境)

3 篇文章 0 订阅
1 篇文章 0 订阅

Spring框架探索:

​ spring作为一款轻量级的java开发框架,以其优越的特性被广泛使用在各个项目中。它主要提供两个功能IOC、AOP控制反转(依赖注入)和切面,极大的简化了工作者的开发工作。可它是如何工作的以及设计思路如何?接下来我们一起来探索。

​ spring boot的启动以添加了SpringBootApplication注解的类的SpringApplication.run方法开始。

//自动扫描注解
@SpringBootApplication(scanBasePackages="com.imooc")
//@EnableAspectJAutoProxy(proxyTargetClass=true)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

​ SpringApplication的构造方法,这里会初始化一些工厂类。后面会通过这些类来获得环境的处理类和注入一些具体的处理过程中所需要的处理类。

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  //判断具体的web类型
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
  //设置初始化器类
   setInitializers((Collection) 									
   		getSpringFactoriesInstances(ApplicationContextInitializer.class));
  //设置监听器类
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  //主类加载,根据main方法判断
   this.mainApplicationClass = deduceMainApplicationClass();
}

​ 获取web类型deduceFromClasspath,这里通过ClassUtils.isPresent方法来判断我们引入类的类型进而判断是否是响应式编程。ClassUtils.isPresent方法即是一个Class.forName方法的调用,即类加载过程,这里不具体介绍。

private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
			"org.springframework.web.context.ConfigurableWebApplicationContext" };


static WebApplicationType deduceFromClasspath() {
  //这里通过判断是否引入类来判断具体的类型
  //包含WEBFLUX_INDICATOR_CLASS不包含WEBMVC_INDICATOR_CLASS、WEBMVC_INDICATOR_CLASS来判断
  //也可以自己配置web的自动注入类
  //这里默认为servlet
   if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
         && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
      return WebApplicationType.REACTIVE;
   }
  //是否有自动配置类
   for (String className : SERVLET_INDICATOR_CLASSES) {
      if (!ClassUtils.isPresent(className, null)) {
         return WebApplicationType.NONE;
      }
   }
   return WebApplicationType.SERVLET;
}

获取注入过程和环境配置需要的类getSpringFactoriesInstances

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
   ClassLoader classLoader = getClassLoader();
   // 载入需要的类,根据spring.properties配置文件获取类名
   Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
  //类的实例化
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
  //排序
   AnnotationAwareOrderComparator.sort(instances);
   return instances;
}

​ 通过类名载入具体的工厂类



public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
   String factoryTypeName = factoryType.getName();
  //具体载入工厂类和其它处理类的过程
   return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

​ 遍历获取类名

//工厂类的具体目录
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
//处理过程
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {

	MultiValueMap<String, String> result = cache.get(classLoader);
	if (result != null) {
		return result;
	}

	try {
      	//获取路径信息
		Enumeration<URL> urls = (classLoader != null ?
				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 properties = PropertiesLoaderUtils.loadProperties(resource);
			for (Map.Entry<?, ?> entry : properties.entrySet()) {
				String factoryTypeName = ((String) entry.getKey()).trim();
              	//这里配置文件可能存在一个key对应多个value以","分割的情况
				for (String factoryImplementationName : 											StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
					result.add(factoryTypeName, factoryImplementationName.trim());
				}
			}
		}
		cache.put(classLoader, result);
		return result;
	}
	catch (IOException ex) {
		throw new IllegalArgumentException("Unable to load factories from location [" +
				FACTORIES_RESOURCE_LOCATION + "]", ex);
	}
}

​ 工厂类的实例化过程,这里是根据构造函数获取类的实例。

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;
}

​ 通过构造函数进行实例化

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
   Assert.notNull(ctor, "Constructor must not be null");
      ReflectionUtils.makeAccessible(ctor);
     //这里判断是否是Kotlin编程
      if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
         return KotlinDelegate.instantiateClass(ctor, args);
      }
      else {
         Class<?>[] parameterTypes = ctor.getParameterTypes();
         Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments 			than constructor parameters");
         Object[] argsWithDefaultValues = new Object[args.length];
         for (int i = 0 ; i < args.length; i++) {
            if (args[i] == null) {
               Class<?> parameterType = parameterTypes[i];
              //根据是否基本类型赋默认值
               argsWithDefaultValues[i] = (parameterType.isPrimitive() ? 								DEFAULT_TYPE_VALUES.get(parameterType) : null);
            }
            else {
               argsWithDefaultValues[i] = args[i];
            }
         }
        //通过构造函数来进行实例化
         return ctor.newInstance(argsWithDefaultValues);
      }
}

​ SpringBoot的run方法具体实

public ConfigurableApplicationContext run(String... args) {
  //这里是一个运行监视
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
  //配值System的headless属性
   configureHeadlessProperty();
  //获取监听器,监听器比较常用,环境配置到实例销毁都有用到。内部有多个监听类是通过前面的		     	//SpringApplication类初始化中的setListener注入进去
   SpringApplicationRunListeners listeners = getRunListeners(args);
  //起始方法的监听
   listeners.starting();
   try {
     
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
     //环境准备
      ConfigurableEnvironment environment = prepareEnvironment(listeners, 						applicationArguments);
     //忽略的BeanInfo
      configureIgnoreBeanInfo(environment);
     //横幅的输出
      Banner printedBanner = printBanner(environment);
     //ApplicationContext类
      context = createApplicationContext();
     //异常处理类
      exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
     //配置Context类
      prepareContext(context, environment, listeners, applicationArguments, printedBanner);
      //依赖注入的入口
      refreshContext(context);
      //注入结束处理
      afterRefresh(context, applicationArguments);
      //监控结束
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), 			stopWatch);
      }
      //注入结束后的监听事件触发
      listeners.started(context);
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }

   try {
      //运行时触发监听
      listeners.running(context);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
   return context;
}

​ 事件的发布使用观察者模式进行处理,根据事件的不同对事件进行过滤,符合条件的事件会被执行。starting方法只会调用log日志的loggingSystem的选择,org.springframework.boot.logging.LoggingSystem配置项可以选择,默认按顺序加载。getApplicationListeners方法是对事件的过滤处理。事件的发布是通过multicastEvent方法进行调用,循环调用具体事件的onApplicationEvent方法执行事件,事件发布具体过程不进行详细介绍。

protected Collection<ApplicationListener<?>> getApplicationListeners(
      ApplicationEvent event, ResolvableType eventType) {

   Object source = event.getSource();
   Class<?> sourceType = (source != null ? source.getClass() : null);
  //获取缓存中的key值
   ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

   // 获取缓存中的需要执行的事件,成功直接返回
   ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
   if (retriever != null) {
      return retriever.getApplicationListeners();
   }

   if (this.beanClassLoader == null ||
         (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
               (sourceType == null || ClassUtils.isCacheSafe(sourceType, 								this.beanClassLoader)))) {
      // 对事件的处理进行加锁处理,防止事件重复处理
      synchronized (this.retrievalMutex) {
        // 再次获取缓存中的需要执行的事件,成功直接返回
         retriever = this.retrieverCache.get(cacheKey);
         if (retriever != null) {
            return retriever.getApplicationListeners();
         }
         retriever = new ListenerRetriever(true);
        //具体的过滤处理
         Collection<ApplicationListener<?>> listeners =
               retrieveApplicationListeners(eventType, sourceType, retriever);
         this.retrieverCache.put(cacheKey, retriever);
         return listeners;
      }
   }
   else {
      return retrieveApplicationListeners(eventType, sourceType, null);
   }
}

​ 过滤方法retrieveApplicationListeners

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
      ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever 		retriever) {

   List<ApplicationListener<?>> allListeners = new ArrayList<>();
   Set<ApplicationListener<?>> listeners;
   Set<String> listenerBeans;
   synchronized (this.retrievalMutex) {
      listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
      listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
   }
//这里是spring boot的工厂类扫描进来的监听类的过滤处理
   for (ApplicationListener<?> listener : listeners) {
     //这时具体的过滤方法,通过事件类型和目标事件类型来进行匹配。具体的既是两个类型比较
      if (supportsEvent(listener, eventType, sourceType)) {
         if (retriever != null) {
            retriever.applicationListeners.add(listener);
         }
         allListeners.add(listener);
      }
   }
//这里是我们自定义的事件类,通过registerListeners注入进去。这里会在扫描整个目录后,加入进来
   if (!listenerBeans.isEmpty()) {
      ConfigurableBeanFactory beanFactory = getBeanFactory();
      for (String listenerBeanName : listenerBeans) {
         try {
           //对自定义事件的过滤
            if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
              //这里有一个getBean是依赖注入的具体实现
               ApplicationListener<?> listener =
                     beanFactory.getBean(listenerBeanName, ApplicationListener.class);
               if (!allListeners.contains(listener) && supportsEvent(listener, eventType, 					sourceType)) {
                  if (retriever != null) {
                    //这里有一个是否单例模式的判断,不是单例模式的监听不会加入到retriever中,也就					//不会加入到缓存中
                     if (beanFactory.isSingleton(listenerBeanName)) {
                        retriever.applicationListeners.add(listener);
                     }
                     else {
                        retriever.applicationListenerBeans.add(listenerBeanName);
                     }
                  }
                  allListeners.add(listener);
               }
            }
            else {
              //过滤不通过的事件直接移除
               Object listener = beanFactory.getSingleton(listenerBeanName);
               if (retriever != null) {
                  retriever.applicationListeners.remove(listener);
               }
               allListeners.remove(listener);
            }
         }
         catch (NoSuchBeanDefinitionException ex) {
            
         }
      }
   }

   AnnotationAwareOrderComparator.sort(allListeners);
  //加入事件,applicationListenerBeans是通过是否为空通过是否存在多实例对象来判断
   if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
      retriever.applicationListeners.clear();
      retriever.applicationListeners.addAll(allListeners);
   }
   return allListeners;
}

​ 环境的准备prepareEnvironment,这里去获取environment,没有新生成一个environment来保证一个beanFactory只有一个environment。

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments) {
   // 创建environment,如果创建过直接返回原environment
   ConfigurableEnvironment environment = getOrCreateEnvironment();
  //配置环境,这里是完成转换类的格式化类的注入
   configureEnvironment(environment, applicationArguments.getSourceArgs());
  //塞入一个attach的属性,实际是configurationProperties属性
   ConfigurationPropertySources.attach(environment);
  //监听器的执行--环境准备阶段
   listeners.environmentPrepared(environment);
   bindToSpringApplication(environment);
   if (!this.isCustomEnvironment) {
      environment = new 																	EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(
        environment,deduceEnvironmentClass());
   }
   ConfigurationPropertySources.attach(environment);
   return environment;
}

​ 根据webApplicationType判断是StandardServletEnvironment类型的环境。webApplicationType是通过前面的SpringBoot初始化时赋值。

private ConfigurableEnvironment getOrCreateEnvironment() {
   if (this.environment != null) {
      return this.environment;
   }
   switch (this.webApplicationType) {
   case SERVLET:
      return new StandardServletEnvironment();
   case REACTIVE:
      return new StandardReactiveWebEnvironment();
   default:
      return new StandardEnvironment();
   }
}

​ StandardServletEnvironment类的实例化,调用父类的构造方法时会调用customizePropertySources方法来进行propertySources的初始化。这里注意下propertySources的顺序,跟后面@Value注解具体的值有关,存在优先级。

public AbstractEnvironment() {
	customizePropertySources(this.propertySources);
}

//servletContext初始化参数
public static final String SERVLET_CONTEXT_PROPERTY_SOURCE_NAME="servletContextInitParams";

//servletConfig初始化参数
public static final String SERVLET_CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams";

//jndi属性
public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties";

@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
   //servletConfigInitParams、servletContextInitParams、jndiProperties初始化
   propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
   propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
   if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
      propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
   }
   super.customizePropertySources(propertySources);
}

//systemEnvironment系统环境
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";

//systemProperties系统属性
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
  	//systemEnvironment、systemProperties加入到环境中
	propertySources.addLast(
			new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, 			getSystemProperties()));
	propertySources.addLast(
			new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, 	getSystemEnvironment()));
}

​ configureEnvironment类进行环境配置,加入ConversionService类(进行类型转换用)。

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
   if (this.addConversionService) {
      ConversionService conversionService = 										              ApplicationConversionService.getSharedInstance();
      environment.setConversionService((ConfigurableConversionService) conversionService);
   }
   configurePropertySources(environment, args);
  //这里是设置ActiveProfiles,但此时不会设置。
   configureProfiles(environment, args);
}

​ ConversionService获取类型转换类。

public static ConversionService getSharedInstance() {
   ApplicationConversionService sharedInstance =                   		                   		      ApplicationConversionService.sharedInstance;
   if (sharedInstance == null) {
      synchronized (ApplicationConversionService.class) {
         sharedInstance = ApplicationConversionService.sharedInstance;
         if (sharedInstance == null) {
           //这里是初始化注入默认的转换类
            sharedInstance = new ApplicationConversionService();
            ApplicationConversionService.sharedInstance = sharedInstance;
         }
      }
   }
   return sharedInstance;
}

​ 环境准备后置处理触发类

private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
   List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
   postProcessors.add(this);
   AnnotationAwareOrderComparator.sort(postProcessors);
   for (EnvironmentPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessEnvironment(event.getEnvironment(), 
                                           event.getSpringApplication());
   }
}

​ 环境准备监听事件一:后置处理器

​ 后置处理器1:系统环境替换,转换成OriginAwareSystemEnvironmentPropertySource类。

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
   String sourceName = StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME;
   PropertySource<?> propertySource = environment.getPropertySources().get(sourceName);
   if (propertySource != null) {
      replacePropertySource(environment, sourceName, propertySource);
   }
}

@SuppressWarnings("unchecked")
private void replacePropertySource(ConfigurableEnvironment environment, String sourceName,
      PropertySource<?> propertySource) {
   Map<String, Object> originalSource = (Map<String, Object>) propertySource.getSource();
   SystemEnvironmentPropertySource source = new OriginAwareSystemEnvironmentPropertySource(sourceName,
         originalSource);
   environment.getPropertySources().replace(sourceName, source);
}

​ 后置处理器2:

​ 对空的Json属性过滤,这里暂时没有json格式属性,暂不做处理。

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
   MutablePropertySources propertySources = environment.getPropertySources();
   propertySources.stream().map(JsonPropertyValue::get).filter(Objects::nonNull).findFirst()
         .ifPresent((v) -> processJson(environment, v));
}

private void processJson(ConfigurableEnvironment environment, JsonPropertyValue propertyValue) {
   JsonParser parser = JsonParserFactory.getJsonParser();
   Map<String, Object> map = parser.parseMap(propertyValue.getJson());
   if (!map.isEmpty()) {
      addJsonPropertySource(environment, new JsonPropertySource(propertyValue, flatten(map)));
   }
}

​ 后置处理器3:

​ 这里是对云服务的处理,主要是加入虚拟机参数。

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
   if (CloudPlatform.CLOUD_FOUNDRY.isActive(environment)) {
      Properties properties = new Properties();
      JsonParser jsonParser = JsonParserFactory.getJsonParser();
      addWithPrefix(properties, getPropertiesFromApplication(environment, jsonParser), 			"vcap.application.");
      addWithPrefix(properties, getPropertiesFromServices(environment, jsonParser), 			"vcap.services.");
      MutablePropertySources propertySources = environment.getPropertySources();
      if(propertySources.contains(
        CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME)) {
        propertySources.addAfter(
               CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME,
               new PropertiesPropertySource("vcap", properties));
      }
      else {
         propertySources.addFirst(new PropertiesPropertySource("vcap", properties));
      }
   }
}

​ 后置处理器3:

​ RandomValuePropertySource加入到环境中(environment类)。

protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
   RandomValuePropertySource.addToEnvironment(environment);
   new Loader(environment, resourceLoader).load();
}

public static void addToEnvironment(ConfigurableEnvironment environment) {
		environment.getPropertySources().
          addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
				new RandomValuePropertySource(RANDOM_PROPERTY_SOURCE_NAME));
		logger.trace("RandomValuePropertySource add to Environment");
	}
	
	Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
			this.environment = environment;
			this.placeholdersResolver = new 
              PropertySourcesPlaceholdersResolver(this.environment);
			this.resourceLoader = (resourceLoader != null) ? resourceLoader : 
      		new DefaultResourceLoader(null);
			this.propertySourceLoaders = 	
              SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
					getClass().getClassLoader());
		}

​ 后置处理器4:

​ reactordebuger类的加入。

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
   if (ClassUtils.isPresent(REACTOR_DEBUGAGENT_CLASS, null)) {
      Boolean agentEnabled = environment.getProperty(DEBUGAGENT_ENABLED_CONFIG_KEY, Boolean.class);
      if (agentEnabled != Boolean.FALSE) {
         try {
            Class<?> debugAgent = Class.forName(REACTOR_DEBUGAGENT_CLASS);
            debugAgent.getMethod("init").invoke(null);
         }
         catch (Exception ex) {
            throw new RuntimeException("Failed to init Reactor's debug agent", ex);
         }
      }
   }
}

​ 监听器二:是否开启标准化输出日志,可能导致日志错乱慎用。

@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
   ConfigurableEnvironment environment = event.getEnvironment();
   Binder.get(environment).bind("spring.output.ansi.enabled", AnsiOutput.Enabled.class)
         .ifBound(AnsiOutput::setEnabled);
   AnsiOutput.setConsoleAvailable(environment.getProperty("spring.output.ansi.console-available", Boolean.class));
}

​ 监听器三:日志系统处理,包含日志名称、日志路径、日志等级的配置。

private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
   if (this.loggingSystem == null) {
      this.loggingSystem = 
        LoggingSystem.get(event.getSpringApplication().getClassLoader());
   }
   initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader());
}

protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
  		//这里运用日志属性,会有例如日志大小等属性加入(可配置)。
		new LoggingSystemProperties(environment).apply();
		this.logFile = LogFile.get(environment);
		if (this.logFile != null) {
			this.logFile.applyToSystemProperties();
		}
		this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);
  		//初始化日志等级
		initializeEarlyLoggingLevel(environment);
		//初始化日志系统,这里如果设置了配置文件logging.config则直接读取配置文件,没有则在			//"logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml"读取
  		initializeSystem(environment, this.loggingSystem, this.logFile);
		//最终日志等级		
  		initializeFinalLoggingLevels(environment, this.loggingSystem);
  		//日志停止处理类
		registerShutdownHookIfNecessary(environment, this.loggingSystem);
	}
	
	public static final String FILE_NAME_PROPERTY = "logging.file.name";

	public static final String FILE_PATH_PROPERTY = "logging.file.path";
	
	//以给定日志路径和名称创建日志对象
	public static LogFile get(PropertyResolver propertyResolver) {
		String file = propertyResolver.getProperty(FILE_NAME_PROPERTY);
		String path = propertyResolver.getProperty(FILE_PATH_PROPERTY);
		if (StringUtils.hasLength(file) || StringUtils.hasLength(path)) {
			return new LogFile(file, path);
		}
		return null;
	}
	//判断日志等级
	private void initializeEarlyLoggingLevel(ConfigurableEnvironment environment) {
		if (this.parseArgs && this.springBootLogging == null) {
			if (isSet(environment, "debug")) {
				this.springBootLogging = LogLevel.DEBUG;
			}
			if (isSet(environment, "trace")) {
				this.springBootLogging = LogLevel.TRACE;
			}
		}
	}
	//日志配置文件
	private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem 			system, LogFile logFile) {
		LoggingInitializationContext initializationContext = 
          new LoggingInitializationContext(environment);
		String logConfig = environment.getProperty(CONFIG_PROPERTY);
		if (ignoreLogConfig(logConfig)) {
			system.initialize(initializationContext, null, logFile);
		}
		else {
			try {
				system.initialize(initializationContext, logConfig, logFile);
			}
			catch (Exception ex) {
				......
			}
		}
	}

​ 监听器四:预处理设置,通过spring.backgroundpreinitializer.ignore判断是否预处理一些类的处理。主要是一些类的初始化。

public void onApplicationEvent(SpringApplicationEvent event) {
    if (!Boolean.getBoolean("spring.backgroundpreinitializer.ignore") && event 					instanceof ApplicationEnvironmentPreparedEvent && this.multipleProcessors() 			&& 	preinitializationStarted.compareAndSet(false, true)) {
            this.performPreinitialization();
    }

    if ((event instanceof ApplicationReadyEvent || event instanceof 				
         ApplicationFailedEvent) && preinitializationStarted.get()) {
            try {
                preinitializationComplete.await();
            } catch (InterruptedException var3) {
                Thread.currentThread().interrupt();
            }
        }

    }
//这里是一些预加载内容,类的初始化。会单独起一个线程
private void performPreinitialization() {
    try {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                this.runSafely(
                    new BackgroundPreinitializer.ConversionServiceInitializer());
                this.runSafely(new BackgroundPreinitializer.ValidationInitializer());
                this.runSafely(new BackgroundPreinitializer.MessageConverterInitializer());
                this.runSafely(new BackgroundPreinitializer.JacksonInitializer());
                this.runSafely(new BackgroundPreinitializer.CharsetInitializer());
                BackgroundPreinitializer.preinitializationComplete.countDown();
            }

            public void runSafely(Runnable runnable) {
                try {
                    runnable.run();
                } catch (Throwable var3) {
                }

            }
        }, "background-preinit");
        thread.start();
    } catch (Exception var2) {
        preinitializationComplete.countDown();
    }

}

​ 监听器五:判断spring.mandatory-file-encoding配置和file.encoding属性是否一致,不一致直接返回。

public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
   ConfigurableEnvironment environment = event.getEnvironment();
   String desired = environment.getProperty("spring.mandatory-file-encoding");
   if (desired == null) {
      return;
   }
   String encoding = System.getProperty("file.encoding");
   if (encoding != null && !desired.equalsIgnoreCase(encoding)) {
      if (logger.isErrorEnabled()) {
         ......//是一些错误处理的类,直接省略
   }
}

插入spring.beaninfo.ignore属性

private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
   if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
      Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
      System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
   }
}

​ 打印横幅,可以通过配置参数控制也可以指定名称放入程序路径下,支持文件和图片

Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
   Banner banner = getBanner(environment);
   banner.printBanner(environment, sourceClass, out);
   return new PrintedBanner(banner, sourceClass);
}
//获取横幅
private Banner getBanner(Environment environment) {
   Banners banners = new Banners();
   banners.addIfNotNull(getImageBanner(environment));
   banners.addIfNotNull(getTextBanner(environment));
   if (banners.hasAtLeastOneBanner()) {
      return banners;
   }
   if (this.fallbackBanner != null) {
      return this.fallbackBanner;
   }
   return DEFAULT_BANNER;
}
//这是一个图片格式横幅获取方式
private Banner getImageBanner(Environment environment) {
  	//指定横幅路径
	String location = environment.getProperty(BANNER_IMAGE_LOCATION_PROPERTY);
	if (StringUtils.hasLength(location)) {
		Resource resource = this.resourceLoader.getResource(location);
		//返回指定横幅的resource
      	return resource.exists() ? new ImageBanner(resource) : null;
	}
	for (String ext : IMAGE_EXTENSION) {
		Resource resource = this.resourceLoader.getResource("banner." + ext);
		if (resource.exists()) {
			return new ImageBanner(resource);
		}
	}
	return null;
}

​ 根据webApplicationType返回对应上下文环境的类,这里是以类名获取类的类类型,然后获取构造方法进行初始化。

protected ConfigurableApplicationContext createApplicationContext() {
   Class<?> contextClass = this.applicationContextClass;
   if (contextClass == null) {
      try {
         switch (this.webApplicationType) {
         case SERVLET:
            contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
            break;
         case REACTIVE:
            contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
            break;
         default:
            contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
         }
      }
      catch (ClassNotFoundException ex) {
         throw new IllegalStateException("Unable create a default ApplicationContext, 			please specify an ApplicationContextClass", ex);
      }
   }
   return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}	

​ Context类的处理prepareContext

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment 	environment,SpringApplicationRunListeners listeners, ApplicationArguments 			     applicationArguments, Banner printedBanner) {
  //设置环境
   context.setEnvironment(environment);
   postProcessApplicationContext(context);
  //这里是一些初始化,主要是添加一些监听类
   applyInitializers(context);
  //触发监听事件,debug发现并未进行具体事件的处理
   listeners.contextPrepared(context);
  //日志输出
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
   }
   // 获取bean工厂类
   ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
   beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
   if (printedBanner != null) {
      beanFactory.registerSingleton("springBootBanner", printedBanner);
   }
   if (beanFactory instanceof DefaultListableBeanFactory) {
      ((DefaultListableBeanFactory) beanFactory)
            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.lazyInitialization) {
      context.addBeanFactoryPostProcessor(new 				
              LazyInitializationBeanFactoryPostProcessor());
   }
   // Load the sources
   Set<Object> sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   load(context, sources.toArray(new Object[0]));
   listeners.contextLoaded(context);
}

​ 后置处理,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) context).setResourceLoader(this.resourceLoader);
      }
      if (context instanceof DefaultResourceLoader) {
         ((DefaultResourceLoader)context).setClassLoader(
           this.resourceLoader.getClassLoader());
      }
   }
   if (this.addConversionService) {                        	   							     	context.getBeanFactory().setConversionService(
     	ApplicationConversionService.getSharedInstance());
   }
}

​ 载入BeanDefinitionLoader类

//载入BeanDefinitionLoader类
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();
}

int load() {
		int count = 0;
		for (Object source : this.sources) {
			count += load(source);
		}
		return count;
	}

	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());
	}

	private int load(Class<?> source) {
		if (isGroovyPresent() && 					
            GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
			GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, 					GroovyBeanDefinitionSource.class);
			load(loader);
		}
		if (isEligible(source)) {
          	//将annotatedReader注册,留给后面注入使用。
			this.annotatedReader.register(source);
			return 1;
		}
		return 0;
	}

​ spring boot启动以SpringApplication.run方法开始,其中SpringApplication类的初始化会将需要的类提前加入,getSpringFactoriesInstances会将"META-INF/spring.factories"目录下的类名载入供给后面的类使用。然后会调用run方法进行后续环境配置,主要是日志类、环境类的配置以及其他配置项的配置。其中属性的配置会涉及到属性获取,environment类中会有一个propertySource集合,通过PropertySourcesPropertyResolver类可以在获取优先级最高的属性(根据property加入的属性)。spring boot的配置多是以class.forname进行类的加载,然后获取构造函数进行初始化。这样的方式很浪费资源,spring的加载是根据字节码进行加载,更加高效。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值