目录

写在前面

1、入门

1.1、HelloWorld项目

现在: 在pom.xml添加

1.2、Sprigboot项目总结:

1.3、自动配置管理

依赖管理

1.3.1、父项目做依赖管理

1.3.2、开发导入starter场景启动器

1.3.3、无需关注版本号,直接版本仲裁

1.3.4、可以修改版本号

自动配置

1.3.5、按需加载所有自动配置项

2、底层注解-@Configuration详解

3、底层注解-@Import导入组件

4、底层注解-@Conditional条件装配

5、底层注解-@ImportResource导入Spring配置文件

6、底层注解-@ConfigurationProperties配置绑定

6.1

6.2、Spring Boot 一种配置绑定

7.3、Spring Boot 另一种配置绑定

7、自动配置【源码分析】-自动包规则原理

7.1、@SpringBootConfiguration

7.2、@ComponentScan

7.3、@EnableAutoConfiguration

7.3.1、@AutoConfigurationPackage

即Registrar 作用 就是将某个包下的所有 组件 注册到容器中。

7.3.2、@Import(AutoConfigurationImportSelector.class)

​8、自动配置【源码分析】-自动配置流程

8.1、例子1

8.2、例子2

8.3、例子3

8.4、实例4

8.5、实例5

9、总结:

写在前面

雷神课:尚硅谷雷神SpringBoot2零基础入门springboot全套完整版(spring boot2)_哔哩哔哩_bilibili

1、入门

系统要求

  • Java 8
  • Maven 3.3+
  • IntelliJ IDEA 2019.1.2

Maven配置文件
新添内容:

<mirrors><mirror><id>nexus-aliyun</id><mirrorOf>central</mirrorOf><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url></mirror>
</mirrors><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>
</profiles>

1.1、HelloWorld项目

需求:浏览发送/hello请求,响应 “Hello,Spring Boot 2”创建maven工程

父:spring-boot-starter-parent
引入依赖:

  • web支持:spring-boot-starter-web
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.4.RELEASE</version>
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

创建主程序

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MainApplication {public static void main(String[] args) {SpringApplication.run(MainApplication.class, args);}
}

编写业务

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@RequestMapping("/hello")public String handle01(){return "Hello, Spring Boot 2!";}
}

运行&测试
        运行MainApplication类
        浏览器输入http://localhost:8080/hello,将会输出Hello!。

设置配置
maven工程的resource文件夹中创建application.properties文件。

# 设置端口号
server.port=8888

更多配置信息

打包部署

之前是打成war包,然后放到tomcat中运行。

现在: 在pom.xml添加

 <!--  这个插件,可以将应用打包成一个可执行的jar包--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>


        在IDEA的Maven插件上点击运行 clean 、package,把helloworld工程项目的打包成jar包

打包好的 jar 包被生成在helloworld工程项目的target文件夹内

用cmd运行java -jar boot-01-helloworld-1.0-SNAPSHOT.jar,既可以运行helloworld工程项目。

将jar包直接在目标服务器执行即可。

1.2、Sprigboot项目总结:

1、引入依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.4.RELEASE</version><relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies><!-- web支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

2、创建主程序

/*** @SpringBootApplication 标志这个一个Springboot应用*/
@SpringBootApplication
@Slf4j
public class MainApplication {public static void main(String[] args) {SpringApplication.run(MainApplication.class,args);log.info("系统正常启动");}
}

3、编写业务

@RestController  //@RestController = @Controller + @ResponseBody
public class HelloController {@RequestMapping("/hello")public String handle01(){return "hello";}
}

4、测试

直接运行Main

5、简化配置

application.properties:

server.port=8888

6、简化部署

<!--  这个插件,可以将应用打包成一个可执行的jar包-->
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

把项目打成jar 包,直接在目标服务器执行就行。

1.3、自动配置管理

依赖管理

1.3.1、父项目做依赖管理

管理依赖的版本号,默认引入的引来可以不写版本号,有默认值,当然也可以写。

依赖管理
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.4.RELEASE</version>
</parent>上面项目的父项目如下:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.3.4.RELEASE</version>
</parent>它几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制

1.3.2、开发导入starter场景启动器

  • 见到很多 spring-boot-starter-* : *就某种场景
  • 只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
  • 更多SpringBoot所有支持的场景
  • 见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器

所有场景启动器最底层的依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.3.4.RELEASE</version>
    <scope>compile</scope>
</dependency>

1.3.3、无需关注版本号,直接版本仲裁

  • 引入依赖默认都可以不写版本
  • 引入非版本仲裁的jar,要写版本号

1.3.4、可以修改版本号

  • 查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
  • 在当前项目里面重写配置,如下面的代码,则可以替代默认的版本号
<properties><mysql.version>5.1.43</mysql.version>
</properties>

IDEA快捷键:

  • option + command + U:以图的方式显示项目中依赖之间的关系。

自动配置

引入spring-boot-starter-web依赖,会默认包含:

spring-boot-starter-tomcat、spring-web、spring-webmvc

1.3.1、自动配好Tomcat

  • 引入Tomcat依赖。
  • 配置Tomcat

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <version>2.3.4.RELEASE</version>
    <scope>compile</scope>
</dependency>

1.3.2、自动配好SpringMVC

  • 引入SpringMVC全套组件
  • 自动配好SpringMVC常用组件(功能)

1.3.3、自动配好Web常用功能:字符编码问题

  • SpringBoot帮我们配置好了所有web开发的常见场景

public static void main(String[] args) {
    //1、返回我们IOC容器
    ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

//2、查看容器里面的组件
    String[] names = run.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}

1.3.4、默认的包结构

  • 主程序(MainApplication)所在包及其下面的所有子包里面的组件都会被默认扫描进来
  • 无需以前的包扫描配置
  • 想要改变扫描路径
    • @SpringBootApplication(scanBasePackages=“com.lun”)
    • 或者
    • @ComponentScan 指定扫描路径

@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.lun")

1.3.4、各种配置拥有默认值

  • 默认配置最终都是映射到某个类上,如:MultipartProperties
  • 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象

1.3.5、按需加载所有自动配置项

  • 非常多的starter
  • 引入了哪些场景这个场景的自动配置才会开启
  • SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面

2、底层注解-@Configuration详解

  • @Configuration(proxyBeanMethod="true")
  • @Bean:方法名就是bean id,返回值是bean实例,返回类型是bean类型
  • 配置类本身也是组件:是一个代理组件

Full模式与Lite模式

/*** 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的* 2、配置类本身也是组件* 3、proxyBeanMethods:代理bean的方法*      Full(proxyBeanMethods = true)(保证每个@Bean方法被调用多少次返回的组件都是单实例的)(默认)*      Lite(proxyBeanMethods = false)(每个@Bean方法被调用多少次返回的组件都是新创建的)*/
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {/*** Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象* @return*/@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例public User user01(){User zhangsan = new User("zhangsan", 18);//user组件依赖了Pet组件zhangsan.setPet(tomcatPet());return zhangsan;}@Bean("tom")public Pet tomcatPet(){return new Pet("tomcat");}
}@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
public class MainApplication {public static void main(String[] args) {//1、返回我们IOC容器ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);//2、查看容器里面的组件String[] names = run.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}//3、从容器中获取组件Pet tom01 = run.getBean("tom", Pet.class);Pet tom02 = run.getBean("tom", Pet.class);System.out.println("组件:"+(tom01 == tom02));//4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892MyConfig bean = run.getBean(MyConfig.class);System.out.println(bean);//如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。//保持组件单实例User user = bean.user01();User user1 = bean.user01();System.out.println(user == user1);User user01 = run.getBean("user01", User.class);Pet tom = run.getBean("tom", Pet.class);//用户获取的pet是容器中唯一的System.out.println("用户的宠物:"+(user01.getPet() == tom));//true}
}

注意:springboot使用 配置类 代替 bean配置文件

<bean id="user01" class="com.rc.spring.boot.bean.User"><property name="name" value="zhangsan"></property><property name="age" value="18"></property>
</bean>
@Configuration //告诉spring容器这是一个配置类,==配置文件
public class MyConfig {//给容器添加组件,方法名为组件id,返回类型为组件类型,返回的值为组件在容器中的实例。@Bean public User user01(){return new User("zhangsna",18);}
}

最佳实战

  • 配置类 组件之间无依赖关系用Lite模式加速容器启动过程,减少判断

    • 因为使用Lite模式,每次从容器获取组件时不会在容器中再执行判断操作,判断组件是否存在。
  • 配置类 组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式(默认)
    • 容器中bean相互依赖时,full模式能保证调用的依赖组件是同一个。

3、底层注解-@Import导入组件

  • @Bean、@Component、@Controller、@Service、@Repository,它们是Spring的基本标签,在Spring Boot中并未改变它们原来的功能。
  • @ComponentScan 在07、基础入门-SpringBoot-自动配置特性有用例。
  • @Import({User.class, DBHelper.class}) 给容器中自动创建出这两个类型的组件默认组件的名字(beanid)就是全限定类名
  • @Import放在容器中 各种组件类 上面即可。
@Import({User.class, DBHelper.class})
@Configuration
public class MyConfig {@Bean public User user01(){return new User("zhangsna",18);}@Bean("cat02")public Pet cat(){return new  Pet("tomcat");}}@SpringBootApplication(scanBasePackages = "com.rc.spring.boot")
@Slf4j
public class MainApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class, args);String[] beanNamesForType = context.getBeanNamesForType(User.class);for (String s : beanNamesForType) {System.out.println(s);}//com.rc.spring.boot.bean.User//user01DBHelper bean1 = context.getBean(DBHelper.class);System.out.println(bean1);//ch.qos.logback.classic.db.DBHelper@61942c1}
}

4、底层注解-@Conditional条件装配

  • 条件装配:满足Conditional指定的条件时,才进行组件注入
  • 以前标注@Bean的都会注册到容器中
  • @Conditional可以标注在类上,或方法上

举例:

用@ConditionalOnBean举例说明,user有一只猫,即存在依赖关系,故需要实现当容器中没有猫组件时,user组件也不注册到容器中。

@Configuration(proxyBeanMethods = false)
public class MyConfig {//在容器中有tom名字的Bean时,user01的bean才会注册到容器中。否则不会注册@ConditionalOnBean(name = "tom")@Beanpublic User user01(){User zhangsan = new User("zhangsan", 18);zhangsan.setPet(tomcatPet());return zhangsan;}public Pet tom(){return new Pet("tomcat");}
}

@ConditionOnBeanname="tom")标注在类上:是说只有在容器中有名字为 tom 的bean时,该类里的所有bean才会生效。否则不生效

@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(name = "tom")//有tom名字的Bean时,MyConfig类的Bean才能生效。
public class MyConfig {@Beanpublic User user01(){User zhangsan = new User("zhangsan", 18);zhangsan.setPet(tomcatPet());return zhangsan;}@Bean("tom22")public Pet tomcatPet(){return new Pet("tomcat");}
}public static void main(String[] args) {//1、返回我们IOC容器ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);//2、查看容器里面的组件String[] names = run.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}boolean tom = run.containsBean("tom");System.out.println("容器中Tom组件:"+tom);//falseboolean user01 = run.containsBean("user01");System.out.println("容器中user01组件:"+user01);//trueboolean tom22 = run.containsBean("tom22");System.out.println("容器中tom22组件:"+tom22);//true}

5、底层注解-@ImportResource导入Spring配置文件

比如,正常使用全注解开发后,bean.xml文件的内容已经不使用了,即里面的bean不会注册到容器中。

然而,有些公司以前使用bean.xml文件生成配置bean,当我们想继续复用bean.xml,不想全部改成注解的形式时,可以使用@ImportResource 来让bean.xml 继续生效,保证xml中的bean注册到容器中。

bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans ..."><bean id="haha" class="com.lun.boot.bean.User"><property name="name" value="zhangsan"></property><property name="age" value="18"></property></bean><bean id="hehe" class="com.lun.boot.bean.Pet"><property name="name" value="tomcat"></property></bean>
</beans>

使用:

@Import({User.class, DBHelper.class})
@Configuration //告诉spring容器这是一个配置类,==配置文件
@ConditionalOnMissingBean(name="tom")
@ImportResource("classpath:bean.xml")
public class MyConfig {}
public static void main(String[] args) {//1、返回我们IOC容器ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);boolean haha = run.containsBean("haha");boolean hehe = run.containsBean("hehe");System.out.println("haha:"+haha);//trueSystem.out.println("hehe:"+hehe);//true
}

6、底层注解-@ConfigurationProperties配置绑定

6.1

只有在容器中的组件,才能拥有springboot 提供的强大功能,即容器提供的强大功能,即才能使用容器里的使用组件。

如何使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用

传统方法:

public class getProperties {public static void main(String[] args) throws FileNotFoundException, IOException {Properties pps = new Properties();pps.load(new FileInputStream("a.properties"));Enumeration enum1 = pps.propertyNames();//得到配置文件的名字while(enum1.hasMoreElements()) {String strKey = (String) enum1.nextElement();String strValue = pps.getProperty(strKey);System.out.println(strKey + "=" + strValue);//封装到JavaBean。}}}

6.2、Spring Boot 一种配置绑定

@ConfigurationProperties + @Component

1、配置文件application.properties

mycar.brand=BYD
mycar.price=100000

2、使用@ConfigurationProperties(prefix="mycar")

将 文件内容和 实体 绑定。注意加上@Component表示是容器中组件

@Data
@NoArgsConstructor
@AllArgsConstructor
@ConfigurationProperties(prefix = "mycar")
@Component
public class Car {String price;String branch;
}

3、验证

@RestController  //@RestController = @Controller + @ResponseBody
public class HelloController {@Autowiredprivate Car car;@RequestMapping("/car")public Car getCar(){return car;}
}


只有在容器中的组件,才会拥有SpringBoot提供的强大功能

7.3、Spring Boot 另一种配置绑定

  • @EnableConfigurationProperties + @ConfigurationProperties
  • 一定 在配置类上 写 @EnableConfigurationProperties(Car.class)
    • 开启Car配置绑定功能
    • 把这个Car这个组件自动注册到容器中
  • 在实体类上 @ConfigurationProperties(prefix="mycar")

application.properties

server.port=8888

mycar.branch=bmw

mycar.price=100000

@Import({User.class, DBHelper.class})
@Configuration //告诉spring容器这是一个配置类,==配置文件
@ConditionalOnMissingBean(name="tom")
@ImportResource("classpath:beans.xml")
@EnableConfigurationProperties(Car.class)
public class MyConfig {}@Data
@NoArgsConstructor
@AllArgsConstructor
@ConfigurationProperties(prefix = "mycar")
//@Component
public class Car {String price;String branch;
}

7、自动配置【源码分析】-自动包规则原理

@SpringbootApplicaion

@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 {...
}

重点分:

@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan

7.1、@SpringBootConfiguration

@Configuration代表当前是一个配置类。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

7.2、@ComponentScan

指定扫描哪些Spring注解

7.3、@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)

public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

Class<?>[] exclude() default {};

String[] excludeName() default {};
}

7.3.1、@AutoConfigurationPackage

自动配置包,指定了默认的包规则。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)  //给容器中导入一个组件
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

Class<?>[] basePackageClasses() default {};
}

  1. 利用Registrar给容器中导入一系列组件
  2. 将指定的一个包下的所有组件导入进MainApplication所在包下。

Registrar 作用 就是将某个包下的所有 组件 注册到容器中。

7.3.2、@Import(AutoConfigurationImportSelector.class)

public class AutoConfigurationImportSelector{

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry   getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);configurations = removeDuplicates(configurations);Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
}
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;
}

}

public final class SpringFactoriesLoader {

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {

String factoryTypeName = factoryType.getName();

return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());

}

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);if (result != null) {return result;} else {try {Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories"): ClassLoader.getSystemResources("META-INF/spring.factories");LinkedMultiValueMap result = new LinkedMultiValueMap();
  • 利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
  • 调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类(共127个自动配置类,就是在配置文件里写死的,命名为xxxAutoConfiguration)
  • 利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
  • 从META-INF/spring.factories位置来加载一个文件。(在我们引入的所有jar包里,有的meta-inf里没有内容,有的有spring.factories)
    • 默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
    • spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
  • 虽然我们127个场景的所有自动配置启动的时候默认全部加载,但是xxxxAutoConfiguration按照条件装配规则(@Conditional),最终会按需配置
  • 文件里面写死了启动配置类,共127个,springboot一启动就要从容器中加载所有的配置类。
  • 文件位置:weispring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories

AopAutoConfiguration类。

按需加载的条件装配:满足条件才能生效。下面aop里面不满足条件,Advice标红不能生效。

8、自动配置【源码分析】-自动配置流程

8.1、例子1

DispatcherServletAutoConfiguration的内部DispatcherServletConfiguration:

方法会从容器中找MultipartResolver类型的解析器,找到后赋值给resolver返回。

@Bean
@ConditionalOnBean(MultipartResolver.class)  //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范// Detect if the user has created a MultipartResolver but named it incorrectlyreturn resolver;//给容器中加入了文件上传解析器;
}

8.2、例子2

看CacheAutoConfiguration是否生效。

@ConditionalOnClass(CacheManager.class):首先找下CacheManager是否存在:双击shift,搜索CacheManager,在spring-context中故存在。

然后查看CacheAspectSupport类型的bean

//查找CacheAspectSupport类型的组件在容器中存在几个
String[] CacheAspectSupport =        context.getBeanNamesForType(CacheAspectSupport.class); System.out.println("CacheAspectSupport.length:" + CacheAspectSupport.length); //CacheAspectSupport.length
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheAspectSupport.class)
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureAfter({ CouchbaseDataAutoConfiguration.class, HazelcastAutoConfiguration.class,HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
@Import({ CacheConfigurationImportSelector.class, CacheManagerEntityManagerFactoryDependsOnPostProcessor.class })
public class CacheAutoConfiguration {

8.3、例子3

看DispatcherServletAutoConfiguration是否生效。

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)public class DispatcherServletAutoConfiguration {
}

@ConditionalOnClass(DispatcherServlet.class) 首先找下DispatcherServlet是否存在:双击shift,搜索DispatcherServlet,在spring-web中故存在。

8.4、实例4

看 DispatcherServletAutoConfiguration中的内部类DispatcherServletConfiguration是否生效。

@Configuration(proxyBeanMethods = false)
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration {

@ConditionalOnClass(ServletRegistration.class):首先找下ServletRegistration是否存在:双击shift,搜索ServletRegistration,在tomcat-embed-core中故存在。

@EnableConfigurationProperties(WebMvcProperties.class):开启类WebMvcProperties与配置文件的绑定,即配置文件以spring.mvc为前缀的配置 可以修改 该类中的属性值。然后将WebMvcProperties放到容器中。

@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {private DefaultMessageCodesResolver.Format messageCodesResolverFormat;private Locale locale;private LocaleResolver localeResolver = LocaleResolver.ACCEPT_HEADER;}
 //查找 WebMvcProperties 类型的组件在容器中存在几个String[] WebMvcProperties = context.getBeanNamesForType(WebMvcProperties.class);System.out.println("WebMvcProperties.length:" + WebMvcProperties.length);//WebMvcProperties.length:1

8.5、实例5

HttpEncodingAutoConfiguration:解决请求编码问题,编码的自动解析,解析中文乱码。

如果用户没配置,则系统默认配置,如果用户自己配置了就用用户的。

@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ServerProperties.class) @ConditionalOnWebApplication(type =     ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(CharacterEncodingFilter.class) @ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
}

约定大于配置:SpringBoot默认会在底层配好所有的组件,但是如果用户自己配置了以用户的优先。约定是指用户手动配置的,配置是指Springboot默认配置的。

9、总结:

  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。(xxxxProperties里面读取,xxxProperties和配置文件进行了绑定)。
  • 生效的配置类就会给容器中装配很多组件
  • 只要容器中有这些组件,相当于这些功能就有了。
  • 定制化配置
    • 方法1:用户直接自己@Bean替换底层的组件
    • 方法2:在配置文件修改值,用户去看这个组件是获取的配置文件什么值就去修改
  • xxxxxAutoConfiguration —> 组件 —> 组件从 xxxxProperties里面拿值 ----> application.properties

参考:03、了解自动配置原理 · 语雀

Springboot笔记(2):SpringBoot入门/雷神相关推荐

  1. SpringBoot笔记:SpringBoot集成MinIO分布式文件系统

    文章目录 搭建MinIO集群 SpringBoot集成 添加依赖 添加配置 获取MinioClient MinioUtils完整工具类 测试代码 搭建MinIO集群 首先搭建MinIO的分布式集群,集 ...

  2. SpringBoot笔记:SpringBoot集成SpringbootAdmin监控

    文章目录 SpringBootAdmin是什么 接入配置 server端配置 client端配置 测试效果 SpringBootAdmin是什么 Spring Boot Admin 是一个管理和监控 ...

  3. SpringBoot笔记:SpringBoot启动参数配置

    文章目录 目的 测试代码 配置文件配置 获取自定义参数 项目打包发布 修改启动配置 方式一:系统变量 方式二:命令行参数 springboot启动参数解释 目的 1.熟悉springboot多环境配置 ...

  4. 【SpringBoot笔记】SpringBoot整合Druid数据连接池

    废话少说,按SpringBoot的老套路来. [step1]:添加依赖 <!-- 数据库连接池 --> <dependency><groupId>com.aliba ...

  5. SpringBoot笔记:SpringBoot集成JWT实战

    文章目录 JWT 简介 概念 JWT 的认证流程 优缺点 JWT 消息构成 header playload signature SpringBoot 集成 JWT 实战 maven 依赖 JwtUti ...

  6. SpringBoot笔记系列目录

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过 ...

  7. 精选SpringBoot笔记!华为19级高工亲撰1700页笔记泄露,亏大了

    相比于其他的一些开发框架,Spring Boot 不但使用更加简单,而且功能更加丰富,性能更加稳定而健壮.使用Spring Boot开发框架,不仅能提高开发速度,增强生产效率,从某种意义上,可以说是解 ...

  8. 全网最全,Alibaba技术官甩出的Springboot笔记

    前言: 在目前互联网公司对SpringBoot的使用已经很普遍了,在实际的项目中,我们需要集成各种的插件支持,不仅如此,还有很多可能我们平时不知道,却很方便的操作. 但是市面上真正适合学习的Sprin ...

  9. SpringBoot笔记汇总【动力节点SpringBoot全套教程完整版】

    前言 动力节点的springboot笔记汇总,公开免费. Spring Boot教程 学习地址 动力节点springboot视频教程-专为springboot初学者打造的教程_哔哩哔哩_bilibil ...

  10. SpringBoot系列: RestTemplate 快速入门

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

最新文章

  1. 实时多线程系统的日志实现
  2. c语言大型软件设计的面向对象_C语言跟C++的根本区别以及特点
  3. SpringCloud Hystrix的超时时间配置以及监控平台搭建
  4. Oracle增量跟新
  5. Linux命令篇之tree命令和touch命令
  6. 刷抖音看美腿中毒后,我决定做一款抖音App
  7. xCheckRDCostMerge2NX2N函数流程
  8. DLL注入之全局钩子注入
  9. 小米手机qq邮箱收件服务器,小米手机无法添加邮箱?是你不会设置而已
  10. 【人工智能】一文读懂人脸识别技术
  11. 首届IBC“社会影响力奖”表彰行业多元化、可持续发展和伦理领导
  12. mysql拖库_利用SQL注入漏洞拖库的方法
  13. 采用系统API实现的二维码扫描、识别和生成
  14. 制作可爱的小黄人插图
  15. 招银网络 Java后端面经
  16. 华为p10android版本,华为P10系列什么时候升级安卓8.0?官方给出答案
  17. adb remount失败的一种解决办法
  18. MSN样式的消息提示
  19. ZOJ 3328 Wu Xing(游戏)
  20. 刚进公司就把祖上十八代单传的代码优化了是什么体验?

热门文章

  1. 【软件之道】Origin2017-安装及破解方法
  2. C51单总线时序图分析与底层编程配置(DS18B20为例)
  3. 时间轴插件完善,大事记清晰美观
  4. 我要翻译《Think Python》- 006 第四章 学习案例:接口设计
  5. Vue框架基本页面的使用模板
  6. 平板电脑 android系统升级,【重磅升级】开源平板电脑(FSPAD-733)升级至Andriod6.0系统...
  7. android音乐播放器文章,Android论文音乐播放器文章.doc
  8. 二叉树的遍历及根据遍历反推树的方法详解
  9. 好用的视频消重 如何查看视频md5
  10. vscode最强摸鱼指南,老板站在身后也看不出来的那种