星星博客 »  > 

浅谈springboot的依赖管理与自动配置

目录

  • 依赖管理
  • 自动配置
    • @SpringBootConfiguration
    • @ComponentScan注解
    • @EnableAutoConfaguration注解
      • @AutoConfigurationPackage
      • @Import({AutoConfigurationImportSelector.class})

依赖管理

我们以往使用ssm进行开发时,在pom.xml文件中需要导入非常多的jar包坐标,对于这一点,springboot帮我们进行了封装简化,我们通过导入父项目

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.5</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

这个父项目中又导入了另一个父项目

<parent>
	 <groupId>org.springframework.boot</groupId>
	 <artifactId>spring-boot-dependencies</artifactId>
	 <version>2.4.5</version>
</parent>

在这个父项目中进行了版本控制,就是我们接下来导入的坐标不需要在关系版本。这个是导入父项目的功能。

接下来就是导入具体的场景启动器了。

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

导入了这个场景启动器 springboot就会自动帮我们把这个场景需要常规的依赖都自动导入

自动配置

springboot 还有一个巨强大的功能就是自动配置。以往我们使用ssm需要配置非常非常多的东西。关于这个springbbot也帮我们完成了。springboot的主方法如下

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

自动配置的重点就是@SpringBootApplication注解。它是由三个注解合成为一个注解。

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

@SpringBootConfiguration

这是我们要浅谈的第一个注解。它是这个样子的

@Configuration
public @interface SpringBootConfiguration {
   ……
}

这表示我们的主方法类是一个spring的配置类。接着再往下看,我们再点进@Configuration注解中

@Component
public @interface Configuration {
    ……
}

因为注解最终是作用在主方法类上面的,这是把主方法类当成组件放入容器。

总之:@SpringBootConfiguration注解的作用就是声明主方法类为spring的配置类,并将它作为组件放入容器中

@ComponentScan注解

浅谈的第二个注解。它的作用是其实就是一个包扫描的作用,它扫描到的包最后被谁加载进容器中嘞?这也是接下来要提到的@EnableAutoConfiguration下的@AutoConfigurationPackage 下的@Import({Registrar.class})要做的事情。


@EnableAutoConfaguration注解

它是由两个注解合成的

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
   ……
}

@AutoConfigurationPackage

该注解其实就是将Registrar类当成组件加载进容器中

@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    ……
}

那么Registrar类到底有什么用,为什么要把它加载进容器中嘞?

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
	……
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
    }
    ……
}

上面的这个方法中的第一个参数是一个元注解对象,因为注解最终是作用在主方法类上面的,从方法体中就可以看出来,这其实是把主方法类所在的包名,将此包名封装到一个数组中,使用register()方法注册进去。

总之就是:@AutoComfigurationPackage注解就是通过@Import将Registrat类加载进容器,从而将主方法类所在的包下的所有组件加载进容器中

@Import({AutoConfigurationImportSelector.class})

此注解的作用就是读取spring-boot-autoconfigure-2.4.4.RELEASE.jar下的META-INF路径下的spring.factories文件。这个文件中记录了springboot启动时就要往容器中添加的所有自动配置类。但是这些自动配置类虽然被加载进了容器中但是并没有立刻生效,这是因为@Conditional注解的存在,让这些自动配置类需要满足一定的条件才会生效。

其实如果在pom.xml文件中导入了相应的场景启动器,然后对应的自动配置类再生效,自动配置类中在通过@Bean注解往容器中添加组件。组件需要的值是都是来源于@EnableConfigurationProperties注解下的XXXXProperties.class 。最终的值都是在application.properties文件中。如果我们想要修改容器中某个组件的功能就可以修改配置文件中的值 或者是 直接使用@Bean替换掉容器中自动配置类导入的组件,一般都是以默认用户的优先,这也是使用@Conditional注解来判断的。

总之,一个总体的流程就是导入相应的场景启动器,再通过主方法类上面的@SpringBootApplication注解下的@EnableAutoComfaguration下的@Import({AutoConfigurationImportSelector.class})读取spring.boot.enableautoconfigurationjar包下的META-INF/spring.factories文件,springboot启动时就加载这个文件中定义的自动配置类,但是这些自动配置类因为@Conditional注解选择性的生效。生效后才会通过类中的@Bean注解往容器中添加相应的组件,组件需要的值又是通过@EnableConfigurationProperties(XXXProperties.class)来的,最终的值还是application.properties文件中。我们在使用修改配置文件 或者 @Bean 改变容器中通过自动配置类导入的组件值。
这样一环扣一环其实还是挺有意思的!

相关文章