首页 > 其他分享 >关于SpringBoot AutoConfiguration

关于SpringBoot AutoConfiguration

时间:2023-05-19 18:02:30浏览次数:54  
标签:SpringBoot spring AutoConfiguration autoconfigure class bean 关于 public String

(1)如何导入的自动配置类

首先我们得从@SpringBootApplication注解入手。

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

@SpringBootApplication = @EnableAutoConfiguration + @ComponentScan + @SpringBootConfiguration

@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
    )
    Class<?>[] exclude() default {};

    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "nameGenerator"
    )
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

其中@EnableAutoConfiguration注解是一个组合注解,@AutoConfigurationPackage 表示自动配置包与@Import({AutoConfigurationImportSelector.class})

1、@AutoConfigurationPackage

作用:给Spring容器中导入一个Registrar注册组件

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

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

@AutoConfigurationPackage和@ComponentScan一样,也是将主配置类所在的包以及子包里面的组件扫描到IOC容器中,但是区别是 @AutoConfigurationPackage扫描@Enitity、@MapperScan等第三方依赖的注解。 @ComponentScan只扫描@Controller、@Service、@Component、@Repository这些常见注解。所以说这俩注解的对象是不一样的。

2、@Import({AutoConfigurationImportSelector.class})

而@Import({AutoConfigurationImportSelector.class})

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

在AutoConfigurationImportSelector下可以看到 getCandidateConfigurations方法

    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
    }

通过SpringFactoriesLoader.loadFactoryNames()

将spring-boot-autoconfigure-2.3.12.RELEASE.jar/META-INF/spring.factories 下配置导入configurations并返回。

总结自动装配的过程

1、通过各种注解的方式实现类与类之间的依赖关系,容器在启动的时候SpringApplication.run(),调用了EnableAutoConfigurationImportSelector.class的selectImports方法。

2、selectImporys方法调用了SpringFactoriesLoader.loadFactoryNames方法扫描jar包类路径下的META-INF/spring.factories文件下获取BEANConfiguration列表。

3、loadFactoryNames方法会读取spring.factoris文件中EnableAutoConfiguration.class类对应的值。

4、根据类上的注解判断,若符合条件则改配置类生效,将配置文件中的属性值配置到对应的配置类中,最后注入到IOC容器中实现自动配置。

(2)@Conditional 的魔力

为了让有条件性注册 Spring bean 变得更加灵活,Spring 4 引入了 @Conditional 概念。通过使用 @Conditional 方式,你可以根据任意条件注册一个 bean。

例如,你可能想在如下情况注册一个 bean:

  • classpath 中某个类
  • 某种类型的 Spring bean,尚未在 ApplicationContext 中注册
  • 存放在某个位置的某个文件
  • 一个存在于配置文件中的某个属性值
  • 一个存在/不存在的某个系统属性

这里只是列举了几个例子,你可以根据自己的需要定义任何条件。

让我们来看看 Spring 的 @Conditional 是如何工作的。

假设我们有一个 UserDAO 接口,其包含从数据存储中获取数据的方法。我们有两个 UserDAO 接口的实现,即 JdbcUserDAO(与 MySQL 数据库通信)和 MongoUserDAO(与 MongoDB 通信)。

我们可能想通过基于系统属性 dbType 来只启用 JdbcUserDAOMongoUserDAO 其中一个。

如果应用程序使用了 java -jar myapp.jar -DdbType = MySQL 启动,则启用 JdbcUserDAO,如果启动时使用了 java -jar myapp.jar -DdbType = MONGO,则启用 MongoUserDAO

假设我们有 UserDAO 接口,以下是 JdbcUserDAOMongoUserDAO 实现类:

public interface UserDAO
{
    List<String> getAllUserNames();
}
 
public class JdbcUserDAO implements UserDAO
{
    @Override
    public List<String> getAllUserNames()
    {
        System.out.println("**** Getting usernames from RDBMS *****");
        return Arrays.asList("Siva","Prasad","Reddy");
    }
}
 
public class MongoUserDAO implements UserDAO
{
    @Override
    public List<String> getAllUserNames()
    {
        System.out.println("**** Getting usernames from MongoDB *****");
        return Arrays.asList("Bond","James","Bond");
    }
}

我们可以实现一个 MySQLDatabaseTypeCondition Condition 来检查系统属性是否是 MYSQL

public class MySQLDatabaseTypeCondition implements Condition
{
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata)
    {
        String enabledDBType = System.getProperty("dbType");
        return (enabledDBType != null && enabledDBType.equalsIgnoreCase("MYSQL"));
    }
}

现在我们可以使用 @Conditional 条件性地配置 JdbcUserDAOMongoUserDAO bean,如下所示:

@Configuration
public class AppConfig
{
    @Bean
    @Conditional(MySQLDatabaseTypeCondition.class)
    public UserDAO jdbcUserDAO(){
        return new JdbcUserDAO();
    }
 
    @Bean
    @Conditional(MongoDBDatabaseTypeCondition.class)
    public UserDAO mongoUserDAO(){
        return new MongoUserDAO();
    }
}

如果我们使用 java -jar myapp.jar -DdbType = MYSQL 来运行应用程序,则只有 JdbcUserDAO bean 被注册。

但如果将系统属性设置为 -DdbType = MONGODB,则只会注册 MongoUserDAO bean。

使用注解实现 Condition 的方式更为优雅,我们可以创建一个 DatabaseType 注解,如下所示:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Conditional(DatabaseTypeCondition.class)
public @interface DatabaseType
{
    String value();
}

然后可以通过编写 DatabaseTypeCondition 使用 DatabaseType 的值来确定是否启用或禁用 bean 注册,如下所示:

public class DatabaseTypeCondition implements Condition
{
    @Override
    public boolean matches(ConditionContext conditionContext,
    AnnotatedTypeMetadata metadata)
    {
        Map<String, Object> attributes = metadata.getAnnotationAttributes(DatabaseType.class.getName());
        String type = (String) attributes.get("value");
        String enabledDBType = System.getProperty("dbType","MYSQL");
        return (enabledDBType != null && type != null && enabledDBType.equalsIgnoreCase(type));
    }
}

现在我们可以将 @DatabaseType 注解放置在 bean 定义上:

@Configuration
@ComponentScan
public class AppConfig
{
    @DatabaseType("MYSQL")
    public UserDAO jdbcUserDAO(){
        return new JdbcUserDAO();
    }
 
    @Bean
    @DatabaseType("MONGO")
    public UserDAO mongoUserDAO(){
        return new MongoUserDAO();
    }
}

此处,我们从 DatabaseType 注解获取元数据,并检查系统属性 dbType 的值以确定是否启用或禁用 bean 注册。

我们已经看了许多示例,了解了如何使用 @Conditional 注解条件性地注册 bean。

SpringBoot 大量地使用了 @Conditional 特性,根据各种标准条件性地注册 bean。

你可以在 Spring-boot-autoconfigure- {version} .jarorg.springframework.boot.autoconfigure 包中找到 SpringBoot 使用的各种 Condition 实现。

(3)如何关闭自动配置

全体无效化

a)使用@Configuration @ComponentScan 代替 @SpringBootApplication。

b)参数设置
src/main/resources/application.properties

设置spring.boot.enableautoconfiguration=false

部分无效化

@SpringBootApplication(exclude=HibernateJpaAutoConfiguration.class)  


src/main/resources/application.properties

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
@SpringBootApplication(exclude={DataSourceAutoConfiguration.**class**, DataSourceTransactionManagerAutoConfiguration.**class**, HibernateJpaAutoConfiguration.**class**}) 

src/main/resources/application.properties

spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.autoconfigure.exclude[2]=org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
spring.autoconfigure.exclude[3]=org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration

以上内容均来自下面三篇文章,本人只是自己做了个总结,方便以后学习,如有侵权,请告知我,马上删除!

引用:

SpringBoot自动装配以及原理 - Be_Your_Sun - 博客园 (cnblogs.com)
Spring Boot 入门 - 进阶篇(7)- 自动配置(AutoConfigure) - Fish Where The Fish Are - ITeye博客
了解 Spring Boot AutoConfiguration - oopsguy - 博客园 (cnblogs.com)

了解 Spring Boot AutoConfiguration - oopsguy - 博客园 (cnblogs.com)

标签:SpringBoot,spring,AutoConfiguration,autoconfigure,class,bean,关于,public,String
From: https://www.cnblogs.com/BestJaxXu/p/17415860.html

相关文章

  • springboot开启跨域security也开启跨域配置
    springboot开启跨域security也开启跨域配置浏览器同源策略,导致跨域失败,添加了security框架后,因为安全框架有一些列的过滤器,即使springboot把跨域打开,security的过滤器也可以能拦截。所以,如果要在服务器端设置,要改两处 方法一:先开放springboot的跨域 再开启security的跨......
  • SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息
    SpringBoot实现WebSocket发送接收消息+Vue实现SocketJs接收发送消息参考:1、https://www.mchweb.net/index.php/dev/887.html2、https://itonline.blog.csdn.net/article/details/81221103?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2......
  • springboot 2.4 版本后的多环境配置
    beanpackagecom.example.demo.tt;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Component;importjavax.annotation.PostConstruct;@ComponentpublicclassTT{@Value("${test.ww}")pub......
  • ④ActiveMQ 与 SpringBoot 集成——(动力节点)ActiveMQ笔记
    第四章ActiveMQ与SpringBoot集成4-1ActiveMQ与SpringBoot集成集成配置1、加载springboot的activeMQ的依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><depen......
  • SpringBoot整合knife4j(swagger)
    关于knife4jKnife4j是一个基于Swagger的Java接口文档生成工具,它提供了一套可视化的界面来展示和测试API接口。Knife4j通过解析接口代码中的Swagger注解,自动生成接口文档,并提供了交互式的API文档界面,方便开发者查看和测试接口。引用官方的一句描述Knife4j是一个集Swagger2和Open......
  • 关于/proc/id/status中内容的描述
    Name:gedit/*进程的程序名*/State:S(sleeping)/*进程的状态信息Tgid:9744/*线程组号*/Pid:9744/*进程pid*/PPid:7672/*父进程的pid*/TracerPid:0/*跟踪进程的pid*/Uid:1000100010001000/*uideuidsuidfsuid*/Gid:1000100010001......
  • 关于前端的一些实用网站推荐
    一、UI框架(对于后台管理模块这俩ui插件足够,都是基于vue开发的)1.antDesign :https://ant.design/index-cn2.elementUI:https://element-plus.gitee.io/zh-CN/ 二、交互设计(与产品设计交接工作非常方便)1.蓝湖:https://lanhuapp.com/dashboard2.figma(很多大厂的选择):https:/......
  • 关于Apple设备私有的apple-touch-icon属性详解
    以前我们用过favicon在浏览器给网站进行身份标识,用法如下:1.<linkhref="http://image.feeliu.com/web/favicon.ico"rel="shortcuticon"/>2.<linkhref="http://image.feeliu.com/web/favicon.ico"rel="Bookmark"/> 现今移动设备越来越多,苹......
  • SpringBoot配置过滤器、拦截器
    拦截器概述SpringBoot提供了一种简单且强大的方式来定义和使用拦截器(Interceptor)。SpringBoot的拦截器基于Spring框架的拦截器机制,可以在请求的处理过程中插入自定义的逻辑。SpringBoot的拦截器主要用于在请求处理的不同阶段执行额外的逻辑操作,比如在请求进入控制器方法之前......
  • 关于ArchLinux 在 Wayland 环境下的问题
    Wayland配置起来确实相对麻烦很多,需要注意很多细节,如果不注意就会出现问题,在这里说一下可能的现象与解决方法。根据观察,这些现象在GNOME与KDE桌面环境钟均会出现。现象App打开慢现象为当首次打开一个图形化的App时,需要等待2-3秒钟才会打开,但是如果已经有一个打开的此......