SpringBoot的自动配置

一、SpringBoot的特点

1)依赖管理

<!--父依赖-->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

<!--父依赖的父依赖-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.4.3</version>
</parent>
<!--在SpringBoot的项目中我们添加依赖几乎不需要我们自己写版本号
		因为在它的父依赖中几乎声明了所有的版本号-->

<!--SpringBoot项目加载场景启动器-->
<!--所有的场景启动器最底层的依赖-->
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.4.3</version>
      <scope>compile</scope>
</dependency>
  • 无效设置版本号,自动闭包仲裁

引入jar默认都可以不设置版本号,自动仲裁
非仲裁jar包,需要自己设定版本号

  • 修改默认仲裁的版本号
<!--首先 查看spring-boot-dependencies里面规定当前依赖的版本 用的 key-->
<!--设置更改-->
<properties>
       <mysql.version>5.1.43</mysql.version>
</properties>

2)自动配置

  • 在SpringBoot中不需要我们自己配置TomCat,它已经帮我们配置好了
  • 自动配置SpringMVC
    • 自动引入、配置SpringMVC组件(功能)
  • 自动配置好web常见功能:字符编码问题等。
    • SpringBoot帮我们配置好了几乎所有的web开发常见场景
  • 默认包结构
    • 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
    • 无需以前的包扫描配置
    • 想要改变扫描路径,使用注解 @SpringBootApplication(scanBasePackages=“com.xin”)
      • 或者@ComponentScan 指定扫描路径
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.xin.boot")
  • 各种配置都拥有默认值
    • 默认配置最终都是映射到某个类上绑定,这个类会在容器中创建对象
  • 按需加载所有自动配置项
    • 非常多的starter,引入了哪些场景这个场景的自动配置才会开启
    • SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面

二、容器功能

1)组件

1、@Configuration
  • Full模式与Lite模式
    • Full模式,(proxyBeanMethods = true),【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
    • Lite模式,Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
    • 组件依赖必须使用Full模式默认。其他默认是否Lite模式
2、@Bean、@Component、@Controller、@Service、@Repository
/*
    Configuration: 告诉SpringBoot,这是一个配置类
    配置类本身就是一个组件
	proxyBeanMethods: 代理Bean的方法,把我们创建代理对象(组件),默认值为 true
			   false: 每一个组件每一次调用时返回的组件都是新创建的,若是类中的各个组件有依赖关系就使用
			   true:  每一个组件每一次调用时返回的组件都是单实例的
 */
@Configuration(proxyBeanMethods = true) //Full模式
//加载配置文件到容器
@ImportResource("classpath:beans.xml")
public class MyConfig {

    @Bean  //给容器中添加组件。以方法名作为组件的id。
    public User user() {
        return new User("张三",18,tomCat());
    }

    @Bean
    public Pet tomCat() {
        return new Pet("tomcat",89.5);
    }
}
3、@ComponentScan、@Import
@Import({User.class, DBHelper.class})
 //给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名

/*
	@ComponentScan:
    
    @AliasFor("basePackages")
    String[] value() default {};
    @AliasFor("value")
    String[] basePackages() default {};
    这两个属性用于指定包路径进行扫描
    nameGenerator: 指定生成的bean的名称
    basePackageClasses: 用于指定某一个类的包的路径进行扫描
    useDefaultFilters: 是否对@Component、@Respository、@Service、@Controller的类进行检测,默认为true
    ComponentScan.Filter[] includeFilters() default {}; 包含过滤条件
*/

//扫描com.xin.pojo包下的没有被注解的Car类
@ComponentScan(value = "com.xin.pojo" ,
        includeFilters =
        {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {Car.class})})

//扫描service包下的类
@ComponentScan(value = "com.xin.service" ,
        useDefaultFilters = true)

4、@Conditional

条件装配:满足Conditional指定的条件,则进行组件注入

2)原生配置文件引入

@ImportResource
//加载配置文件到容器
@ImportResource("classpath:beans.xml")
//路径从根目录下开始

3)配置绑定

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

/**
 * 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
 */
@Component
@ConfigurationProperties(prefix = "mycar")  //取前缀为为mycar的属性值
public class Car {
    ...
}


//若是car实体类上没有使用@Component注解将car注册到容器中那么就要使用@EnableConfigurationProperties注册
//@EnableConfigurationPropertiesz需要注解在配置类上,不能在实体类上


//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
@EnableConfigurationProperties(Car.class)
public class MyConfig {
}

//使用了@ConfigurationProperties注解的实体类必须要在容器中注册,不然会报错

三、自动配置原理入门 – 注解的作用

1)@SpringBootApplication

注解在主程序类上,表示这是一个SpringBoot应用
在它的上面除了四个元注解,还有这三个注解

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}
), @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class})})
public @interface SpringBootApplication {
}

2)@SpringBootConfiguration 与 @Configuration

  • @SpringBootConfiguration    表示SpringBoot的注解类,查看源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

有源码可以看出@SpringBootConfiguration注解内有一个核心注解@Configuration

  • @Configuration 注解是Spring框架提供的

被@Configuration 注解的类,代表是一个配置类,注解以后,就会初始化这个类下所有加了@Bean的方法,并初始化这个bean
由此可知,@SpringBootConfiguration 与 @Configuration的作用相同,都是将一个类标识为配置类,@SpringBootConfiguration 是被SpringBoot 框架进行了重新封装命名的而已

3)@ComponentScan

该注解用来指定哪些Spring注解,定义扫描的路径,默认就会加载标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中, excludeFilters 指定扫描的时候需要排除的组件,includeFilters 指定扫描的时候只包含的组件 ** @filter**过滤器注解
如果不设置value属性,默认扫描路径是启动类所在目录及其子目录
useDefaultFilters :是否对含有@Controller,@Service,@Repository,@Component注解的类开启检测,默认是开启的

@ComponentScan(value = "com.xin.pojo" ,
        useDefaultFilters = true,
        includeFilters =
        {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {Car.class})})
public class MyConfig {
}

4)@EnableAutoConfiguration

进入源码可知,它的内部有两个最主要的注解,@Import,@AutoConfigurationPackage
它的本质上还是一个 @Import注解
作用:帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
}
1. @AutoConfigurationPackage

由源码可知,@AutoConfigurationPackage 注解的核心是@Import 注解
作用:自动配置包,指定默认的包规则

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})  、、//利用Registrar给容器中导入一系列组件
public @interface AutoConfigurationPackage {}
2. @Import
@Import({AutoConfigurationImportSelector.class})
//给容器中批量导入组件
//获取所有需要导入容器中的配置类
//利用工厂加载,得到所有的组件
//默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
//spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

所以说SpringBoot项目在初始化时,会将我们所需要的大多数的组件已经提前帮我们导入容器了。

@SpringBootApplication
public class SpringBootStudyApplication {

	public static void main(String[] args) {
		//返回IOC容器
		ConfigurableApplicationContext context = SpringApplication.run(SpringBootStudyApplication.class, args);

		//查看容器中的组件的数量及名字
		System.out.println("容器中有组件数:" + context.getBeanDefinitionCount());  //springboot内部会自己产生很多的组件
		String[] names = context.getBeanDefinitionNames();
		//遍历组件名
		for (String name : names) {
			System.out.println(name);
		}
    }
}

image.png

image.png
个人理解:@EnableAutoConfiguration,注解的底层是@Import注解,而@Import注解在SpringBoot项目中会帮我们把多数的组件都导入到容器中,在我们的主程序类中的@SpringBootApplication注解的内部又是@EnableAutoConfiguration注解,所以说SpringBoot项目启动时会帮我们加载了许多的组件到容器中,自动的帮我们配置好了绝大多数的东西。

5)@Conditional

条件装配注解,按照我们的需求开启SpringBoot帮我们配置的场景组件
虽然所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration,但是并不是把所有的配置都开启了的,会根据条件来按照我们的需求开启的。开启相应的配置场景,就可以使用相应的组件了,就相当于我们可以使用相应的功能了。

修改默认配置

SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先

@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 incorrectly
    //检测用户是否创建了MultipartResolver但命名不正确
    return resolver;
}
//给容器中加入了文件上传解析器;

总结

  • SpringBoot先加载所有的自动配置类  xxxxxAutoConfiguration

image.png  默认配置类都在这个包中

  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值
  • 生效的配置类就会给容器中装配很多组件
    • 默认的 xxxxxAutoConfiguration 配置类都会和相应的 xxxProperties 文件绑定,从其中去默认值。
  • 只要容器中有这些组件,相当于这些功能就有了

四、小技巧

1)自动配置报告

导入相应的场景依赖项就可以开启相应的配置项,使用其功能。
在配置文件中设置 debug = true ,可以开启自动配置报告,查看开启了那些配置
image.png
image.png

2)Lombok插件

简化JavaBean开发。

  • 安装Lombok插件
  • 导入 Lombok 依赖
<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
</dependency>
  • @Data:

注解在类上;包含了@ToString,@EqualsAndHashCode,@Getter / @Setter和@RequiredArgsConstructor的功能,提供类所有属性的 getter 和 setter 方法,此外还提供了equals、canEqual、hashCode、toString 方法

  • @ToString:

注解在类上;生成toString()方法

  • @Slf4j

注解在类上;根据用户实际使用的日志框架生成log日志对象

  • @Log4j

注解在类上;为类提供一个 属性名为log 的 log4j 日志对象

  • @EqualsAndHashCode

注解在类上;生成hashCode()和equals()方法

  • @NoArgsConstructor:注解在类上;为类提供一个无参的构造方法。
  • @AllArgsConstructor:注解在类上;为类提供一个全参的构造方法
  • @NonNull:  注解在属性上;标识属性是不能为空,为空则抛出异常。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值