1 SpringBoot简介

  • SpringBoot简化Spring应用开发,约定大于配置,去繁从简,just run就能创建一个独立的,产品级别的应用。
  • 背景:
    • J2EE笨重的开发、繁多的配置、低下的开发效率、复杂的部署流程、第三方技术集成难度大。
  • 解决:
    • “Spring全家桶”时代。
    • SpringBoot-->J2EE一站式解决方案。
    • SpringCloud-->分布式整体解决方案。  
  • 优点:
    • 快速创建独立运行的Spring项目以及与主流框架集成。
    • 使用嵌入式的Servlet容器,应用无需打成war包。
    • starters自动依赖和版本控制。
    • 大量的自动配置,简化开发,也可以修改默认值。
    • 无需配置XML,无代码生成,开箱即用。
    • 准生产环境的运行时应用监控。
    • 与云计算的天然集成。  

2 微服务简介

  • 2014年,Martin Fowler与James Lewis共同提出。
  • 微服务是一种架构风格(服务微化)。
  • 一个应用应该是一组小型服务,可以通过HTTP的方式进行互通。
  • 单体应用:ALL IN ONE。
  • 微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元。

3 环境准备

  • JDK1.8。
  • Maven 3.x。
  • IntelliJ IDEA 2019.3。
  • SpringBoot 1.5.9.RELEASE。
  • Maven设置:
  • 给maven的settings.xml配置文件的profiles标签添加如下信息:
<profile>
<id>jdk‐1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>

4 SpringBoot-HelloWorld

4.1 创建Maven项目

  • 略。

4.2 导入SpringBoot相关的依赖

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

4.3 编写主程序,用来启动SpringBoot应用

  • 示例:
  • HelloWorldMainApplication.java
package com.sunxiaping;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication //标注一个主程序类,说明这是一个SpringBoot应用
public class HelloWorldMainApplication {
public static void main(String[] args) {
//SpringBoot应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}

4.3 编写相关的Controller

  • 示例:
  • HelloWorldController.java
package com.sunxiaping.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; @Controller
public class HelloWorldController { @RequestMapping(value = "/hello")
@ResponseBody
public String hello() {
return "helloWorld";
} }

4.4 运行主程序测试

  • 略。

4.5 简化部署

  • 在当前项目的pom.xml中添加如下的配置:
<!-- 这个插件,可以将应用打包成一个可执行的jar包-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
  • 将这个应用打成jar包,然后通过java -jar xxx.jar的命令进行执行。

5 HelloWorld探究

5.1 pom文件

5.1.1 父项目

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent> 其父项目是 <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent> 它是真正管理SpringBoot应用中的所有依赖版本,可以称之为SpringBoot的版本仲裁中心。
所以以后我们导入依赖默认是不需要写版本的,但是如果版本仲裁中心没有的,当然需要写版本号了。

5.1.2 启动器

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • spring-boot-starter:SpringBoot的场景启动器。
  • spring-boot-starter-web:帮助我们导入了web模块正常运行所依赖的组件。
  • SpringBoot将所有的功能场景都抽取出来,做成一个个的starters(启动器),所以我们只需要在项目里引入这些starter,相关场景的所有依赖都会导入进来。
  • 要用什么功能就导入什么场景的启动器。

5.2 主程序类、主入口

  • 示例:
package com.sunxiaping;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication //标注一个主程序类,说明这是一个SpringBoot应用
public class HelloWorldMainApplication {
public static void main(String[] args) {
//SpringBoot应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
  • @SpringBootApplication注解标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就能运行这个类的main方法来启动SpringBoot应用。
package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor; @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication { @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
Class<?>[] exclude() default {}; @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
String[] excludeName() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {}; }
  • @SpringBootConfiguration注解:标注在某个类上,就表明这是一个SpringBoot的配置类,其源码如下所示:
package org.springframework.boot;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.context.annotation.Configuration; @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration { }
  • @Configuration注解,表明这是一个配置类,相当于原来xml格式的applicationContext.xml文件。配置类也是容器中的一个组件,其实@Configuration注解就是@Component注解,其源码如下所示:
package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration { String value() default ""; }
  • @EnableAutoConfiguration注解:开启自动配置功能。以前我们需要配置的东西,SpringBoot帮我们自动配置。@EnableAutoConfiguration注解告诉SpringBoot开启自动配置功能,这样自动配置才能生效。其源码如下:
package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.SpringFactoriesLoader; @SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
  • 其中,@AutoConfigurationPackage注解,是自动配置包的意思,其源码如下:
package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.context.annotation.Import; @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage { }
  • 从源码中,我们可以看出@AutoConfigurationPackage注解会导入AutoConfigurationPackages.Registrar.class组件,其源码如下:
    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

        @Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
       //将当前标注注解类的包下的所有组件注册到Spring容器中 
register(registry, new PackageImport(metadata).getPackageName());
} @Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.<Object>singleton(new PackageImport(metadata));
} }
  • 所以,@SpringBootApplication注解的作用就是将其所在包以及子包下的所有组件都注册到SpringBoot中。
  • 其中,@Import(AutoConfigurationPackages.Registrar.class)将给容器中导入组件,其源码如下所示:
package org.springframework.boot.autoconfigure;

import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.type.AnnotationMetadata; @Deprecated
public class EnableAutoConfigurationImportSelector
extends AutoConfigurationImportSelector { @Override
protected boolean isEnabled(AnnotationMetadata metadata) {
if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {
return getEnvironment().getProperty(
EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
true);
}
return true;
} }
  • 从上面的源码中,我们可以看到EnableAutoConfigurationImportSelector类继承了AutoConfigurationImportSelector,我们知道xxxImportSelector将会将所有需要导入的组件以全类名的方式返回,而这些组件就会被添加到容器中,我们需要查看AutoConfigurationImportSelector的源代码,如下所示:
package org.springframework.boot.autoconfigure;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils; public class AutoConfigurationImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered { private static final String[] NO_IMPORTS = {}; private static final Log logger = LogFactory
.getLog(AutoConfigurationImportSelector.class); private ConfigurableListableBeanFactory beanFactory; private Environment environment; private ClassLoader beanClassLoader; private ResourceLoader resourceLoader; @Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
} protected boolean isEnabled(AnnotationMetadata metadata) {
return true;
} protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
String name = getAnnotationClass().getName();
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(name, true));
Assert.notNull(attributes,
"No auto-configuration attributes found. Is " + metadata.getClassName()
+ " annotated with " + ClassUtils.getShortName(name) + "?");
return attributes;
} protected Class<?> getAnnotationClass() {
return EnableAutoConfiguration.class;
} protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
} protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
} private void checkExcludedClasses(List<String> configurations,
Set<String> exclusions) {
List<String> invalidExcludes = new ArrayList<String>(exclusions.size());
for (String exclusion : exclusions) {
if (ClassUtils.isPresent(exclusion, getClass().getClassLoader())
&& !configurations.contains(exclusion)) {
invalidExcludes.add(exclusion);
}
}
if (!invalidExcludes.isEmpty()) {
handleInvalidExcludes(invalidExcludes);
}
} protected void handleInvalidExcludes(List<String> invalidExcludes) {
StringBuilder message = new StringBuilder();
for (String exclude : invalidExcludes) {
message.append("\t- ").append(exclude).append(String.format("%n"));
}
throw new IllegalStateException(String
.format("The following classes could not be excluded because they are"
+ " not auto-configuration classes:%n%s", message));
} protected Set<String> getExclusions(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
Set<String> excluded = new LinkedHashSet<String>();
excluded.addAll(asList(attributes, "exclude"));
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
excluded.addAll(getExcludeAutoConfigurationsProperty());
return excluded;
} private List<String> getExcludeAutoConfigurationsProperty() {
if (getEnvironment() instanceof ConfigurableEnvironment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
this.environment, "spring.autoconfigure.");
Map<String, Object> properties = resolver.getSubProperties("exclude");
if (properties.isEmpty()) {
return Collections.emptyList();
}
List<String> excludes = new ArrayList<String>();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String name = entry.getKey();
Object value = entry.getValue();
if (name.isEmpty() || name.startsWith("[") && value != null) {
excludes.addAll(new HashSet<String>(Arrays.asList(StringUtils
.tokenizeToStringArray(String.valueOf(value), ","))));
}
}
return excludes;
}
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(getEnvironment(),
"spring.autoconfigure.");
String[] exclude = resolver.getProperty("exclude", String[].class);
return (Arrays.asList(exclude == null ? new String[0] : exclude));
} private List<String> sort(List<String> configurations,
AutoConfigurationMetadata autoConfigurationMetadata) throws IOException {
configurations = new AutoConfigurationSorter(getMetadataReaderFactory(),
autoConfigurationMetadata).getInPriorityOrder(configurations);
return configurations;
} private List<String> filter(List<String> configurations,
AutoConfigurationMetadata autoConfigurationMetadata) {
long startTime = System.nanoTime();
String[] candidates = configurations.toArray(new String[configurations.size()]);
boolean[] skip = new boolean[candidates.length];
boolean skipped = false;
for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
invokeAwareMethods(filter);
boolean[] match = filter.match(candidates, autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
if (!match[i]) {
skip[i] = true;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
}
List<String> result = new ArrayList<String>(candidates.length);
for (int i = 0; i < candidates.length; i++) {
if (!skip[i]) {
result.add(candidates[i]);
}
}
if (logger.isTraceEnabled()) {
int numberFiltered = configurations.size() - result.size();
logger.trace("Filtered " + numberFiltered + " auto configuration class in "
+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)
+ " ms");
}
return new ArrayList<String>(result);
} protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class,
this.beanClassLoader);
} private MetadataReaderFactory getMetadataReaderFactory() {
try {
return getBeanFactory().getBean(
SharedMetadataReaderFactoryContextInitializer.BEAN_NAME,
MetadataReaderFactory.class);
}
catch (NoSuchBeanDefinitionException ex) {
return new CachingMetadataReaderFactory(this.resourceLoader);
}
} protected final <T> List<T> removeDuplicates(List<T> list) {
return new ArrayList<T>(new LinkedHashSet<T>(list));
} protected final List<String> asList(AnnotationAttributes attributes, String name) {
String[] value = attributes.getStringArray(name);
return Arrays.asList(value == null ? new String[0] : value);
} private void fireAutoConfigurationImportEvents(List<String> configurations,
Set<String> exclusions) {
List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
if (!listeners.isEmpty()) {
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this,
configurations, exclusions);
for (AutoConfigurationImportListener listener : listeners) {
invokeAwareMethods(listener);
listener.onAutoConfigurationImportEvent(event);
}
}
} protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class,
this.beanClassLoader);
} private void invokeAwareMethods(Object instance) {
if (instance instanceof Aware) {
if (instance instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) instance)
.setBeanClassLoader(this.beanClassLoader);
}
if (instance instanceof BeanFactoryAware) {
((BeanFactoryAware) instance).setBeanFactory(this.beanFactory);
}
if (instance instanceof EnvironmentAware) {
((EnvironmentAware) instance).setEnvironment(this.environment);
}
if (instance instanceof ResourceLoaderAware) {
((ResourceLoaderAware) instance).setResourceLoader(this.resourceLoader);
}
}
} @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory);
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
} protected final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
} @Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
} protected ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
} @Override
public void setEnvironment(Environment environment) {
this.environment = environment;
} protected final Environment getEnvironment() {
return this.environment;
} @Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
} protected final ResourceLoader getResourceLoader() {
return this.resourceLoader;
} @Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE - 1;
} }
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}

  • 从上面的截图中,我们可以看到会给容器中注册非常多的自动配置类(xxxAutoConfiguration),换言之,就是给容器中导入这个场景所需要的所有组件,并配置好这些组件,有了自动配置了,就免去了我们手动编写配置注入功能组件等工作。
  • 其中,查看下面的代码:
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
    protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
    public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
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);
}
}
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
  • 我们可以知道,将会加载类路径下的META-INF/spring.factories文件中获取EnableAutoConfiguration指定的值,并将这些值作为自动配置类导入到容器中,自动配置类就生效,帮助我们自动配置工作。

  • 总而言之,J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar中。

SpringBoot 1.x 之入门的更多相关文章

  1. SpringBoot系列: RestTemplate 快速入门

    ====================================相关的文章====================================SpringBoot系列: 与Spring R ...

  2. 基于springboot构建dubbo的入门demo

    之前记录了构建dubbo入门demo所需的环境以及基于普通maven项目构建dubbo的入门案例,今天记录在这些的基础上基于springboot来构建dubbo的入门demo:众所周知,springb ...

  3. SpringBoot集成Spring Security入门体验

    一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ...

  4. SpringBoot第一集:入门(2020最新最易懂)

    2020最新SpringBoot第一集:入门(2020最新最易懂) 学习思路: 是什么?为什么要学,有什么用?有什么特点?简单明了的总结一句话! SpringBoot推荐开发工具: Spring To ...

  5. Springboot 完整搭建快速入门,必看!

    前言 手把手教你Springboot微服务项目搭建快速入门,通过本文学习Springboot的搭建快速入门,掌握微服务大致的配置服务,后续将会继续将核心组件引入到项目中,欢迎关注,点赞,转发. Spr ...

  6. SpringBoot学习笔记<一>入门与基本配置

    毕业实习项目技术学习笔记 参考文献 学习视频 2小时学会Spring Boot:https://www.imooc.com/learn/767 学习资料 SpringBoot入门:https://bl ...

  7. SpringBoot整合ActiveMQ快速入门

    Spring Boot 具有如下特性: 为基于 Spring 的开发提供更快的入门体验 开箱即用,没有代码生成,也无需 XML 配置.同时也可以修改默认值来满足特定的需求. 提供了一些大型项目中常见的 ...

  8. SpringBoot 第一篇:入门篇

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10819728.html 版权声明:本文为博主原创文章,转载请附上博文链接! 前言   博主从去年 ...

  9. springboot笔记02——快速入门quickstart

    前言 学习一个新的框架,往往会用一个quickstart快速入门,这次就写一下springboot的quickstart程序. 开发环境 JDK 1.8 Springboot 2.1.6 Maven ...

  10. SpringBoot简介与快速入门

    一.SpringBoot简介 1.1 原有Spring优缺点分析 1.1.1 Spring的优点分析 Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE ...

随机推荐

  1. 二十九:数据库之SQLAlchemy连接数据库

    手写SQL复用性不高,SQL越复杂越容易出bug,而且容易引起SQL注入,所以现在Ibanez使用orm框架将数据库映射为数据模型,这是使用SQLAlchemy 准备工作,安装SQLAlchemy和P ...

  2. MYSQL连接一段时间不操作后出现异常的解决方案

    最近做的网站使用的是MYSQL数据库 发现 果超过8小时应用程序不去访问数据库,数据库就断掉连接 .这时再次访问就会抛出异常,如下所示: com.mysql.jdbc.exceptions.jdbc4 ...

  3. H5、原生app、混合开发三者比较

    一.概念 a) H5:即Html5,接触过互联网的都知道html,所以很明显h5是html的第5次重大修改的一项超文本标记语言的标准协议. b) 原生:使用原生制作APP(Native app),即在 ...

  4. 原生js之addEventListener,removeEventListener

    使用addEventListener添加事件 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  5. python学习之生成器

    4.6 生成器Generrator ​ 生成器本质就是迭代器.python社区生成器与迭代器是一种. ​ 生成器与迭代器的唯一区别:生成器是我们自己用python代码构建的 4.6.1生成器初识 py ...

  6. LeetCode.1002-寻找共有字符(Find Common Characters)

    这是悦乐书的第375次更新,第402篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第236题(顺位题号是1002).给定仅由小写字母组成的字符串A,返回列表中所有字符串都 ...

  7. 转·带你用实例理解C语言回调函数

    原文出处:https://segmentfault.com/a/1190000008293902?utm_source=tag-newest 前言: 如不懂函数指针,请先查阅关于函数指针内容的资料(h ...

  8. 【Qt开发】QT中用函数把float转化成QString

    QT中用函数把float转化成QString 最普通的用法,例如:     float f;     QString str = QString("float is %1").ar ...

  9. [Python3] 027 常用模块 time

    目录 time 1. 时间戳 2. UTC 时间 3. 夏令时 4. 时间元组 5. 举例 5.1 例子1 例子2 例子3 例子4 例子5 例子6 例子7 time 1. 时间戳 一个时间表示,根据不 ...

  10. CF 1136C Nastya Is Transposing Matrices

    题目链接:http://codeforces.com/problemset/problem/1136/C 题目分析 看了题目之后,第一想法:任意位置都可以倒置,要是枚举,铁定的超时.所以需要探索规律. ...