1.什么是springboot自动配置:Auto-Configuration

自动配置指的是在springboot启动时,自动将配置类加载到ioc容器,项目运行时可以直接使用这些配置信息。自动配置为springboot框架的“开箱即用”特点提供了基础支撑

demo:在springboot中使用mongodb

引入 implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

配置mongo服務器

data:
  mongodb:
    collectionName: table-v2
    database: test
    uri: "mongodb://FID:password@\
                                                         hotname/?\
                                                         replicaSet=MGORPST_3004&ssl=true&sslInvalidHostNameAllowed=true"
 

直接使用mongoTemplate或者reactiveMongoTemplate
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(MongoCommonProperties.class)
@Slf4j
@Data
public class MongoConfig extends AbstractMongoClientConfiguration {
  private final MongoCommonProperties properties;

  @Value("${spring.data.mongodb.collectionName}")
  private String collectionName;

  @Value("${spring.data.mongodb.collectionName}-payload")
  private String payloadCollectionName;

  @Value("${spring.data.mongodb.maxLength}")
  private Integer maxLength;

  @Value("${spring.data.mongodb.useGridFs}")
  private boolean useGridFs;

  @Override
  public String getDatabaseName() {
    return properties.getDatabase();
  }

  private static MongoClient mongoClient = null;

  @Override
  public MongoClient mongoClient() {
    if (mongoClient == null) {
      String mongoUri = "";
      String password = "";
      if ("primary".equals(properties.getMongoType())) {
        mongoUri = properties.getUri();
        password = retrievePassword();
      } else {
        mongoUri = properties.getNyuri();
        password = new String(properties.getPassword());
        if (StringUtils.isEmpty(password)) {
          return null;
        }
      }
      ConnectionString connectionString =
          new ConnectionString(mongoUri.replace("password", password));
      MongoClientSettings mongoClientSettings =
          MongoClientSettings.builder().applyConnectionString(connectionString).build();
      mongoClient = MongoClients.create(mongoClientSettings);
    }
    return mongoClient;
  }

  @Primary
  @Bean(name = "mongoTemplate")
  public MongoTemplate getMongoTemplate() {
    if (mongoClient
        != null) { // close mongo client before recreate, because this will lead memory leak
      mongoClient.close();
      mongoClient = null;
    }
    log.info("mongo DB: {}", properties.getDatabase());
    MongoDatabaseFactory mongoDbFactory =
        new SimpleMongoClientDatabaseFactory(mongoClient(), properties.getDatabase());
    return new MongoTemplate(mongoDbFactory, getIndexEnabledMongoConverter(mongoDbFactory));
  }

  private static MongoConverter getIndexEnabledMongoConverter(MongoDatabaseFactory factory) {

    DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
    MongoCustomConversions conversions = new MongoCustomConversions(Collections.emptyList());

    MongoMappingContext mappingContext = new MongoMappingContext();
    mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
    mappingContext.afterPropertiesSet();
    // This is enable auto index
    mappingContext.setAutoIndexCreation(true);

    MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext);
    converter.setCustomConversions(conversions);
    converter.setCodecRegistryProvider(factory);
    converter.afterPropertiesSet();

    return converter;
  }

  /**
   * Retrieve password from CyberArk
   *
   * @return
   */
  public String retrievePassword() {
    StringBuilder stringBuilder = new StringBuilder();
    try {
      URL pass = new URL(properties.getPasswordURL());
      URLConnection yc = pass.openConnection();
      String inputLine;
      try (BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); ) {
        while ((inputLine = in.readLine()) != null) {
          stringBuilder.append(inputLine);
        }
      }
    } catch (IOException e) {
      log.error("Failed to retrieve password from {}", properties.getPasswordURL(), e);
    }
    return stringBuilder.toString();
  }

  @Bean
  public GridFsTemplate gridFsTemplate(
      MongoDatabaseFactory mongoDatabaseFactory, MappingMongoConverter mappingMongoConverter)
      throws Exception {
    return new GridFsTemplate(mongoDatabaseFactory, mappingMongoConverter);
  }

  @Override
  public boolean autoIndexCreation() {
    return true;
  }
}
View Code

 

 

 

直接用以上三步就可以在springboot中使用mongo,整個過程springboot自动完成mongo配置,将相关对象注入到IOC容器中 (面试问IOC时候可以从这个角度回答

2.SpringBoot自动配置流程

2.1 @SpringBootApplication

Springboot启动类添加@SpringBootApplication注解,进入其内部,可以看到@SpringBootApplication是一个组合注解,其内部包含@SpringBootConfigure @EnableAutoConfigure @ComponentScan三个注解。其中@EnableAutoConfiguration便是开启springboot自动配置的注解

2.2 @EnableAutoConfiguration

开启Springboot自动配置,在@EnableAutoConfiguration内部,有@Import(AutoConfigurationImportSelector.class)负责加载所有配置类

2.3 @Import(AutoConfigurationImportSelector.class)流程

2.3.1 读取META-INF/spring.factories文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration下所有自动配置类

2.3.2 过滤排除项(exclude:@EnableAutoConfiguration(exclude={HibernateJpaAutoConfiguration.class});获取在配置文件中spring.autoconfiguration.exclude配置)

2.3.3 应用条件注解,筛选符合条件的配置类

     Spring Boot 提供了一系列内置条件注解,简化常见场景:

  • ‌@ConditionalOnClass/MissingClass‌:检查类是否存在;
  • ‌@ConditionalOnBean/MissingBean‌:检查容器中是否存在特定 Bean;
  • ‌@ConditionalOnProperty‌:基于配置文件属性值决定;
  • ‌@ConditionalOnWebApplication/NotWebApplication‌:判断是否为 Web 应用;
  • ‌@ConditionalOnExpression‌:支持 SpEL 表达式判断。

2.3.4 根据autoconfigureOrder定义的优先级加载配置类

为解决多模块下配置类加载顺序的冲突问题,使用@AutoConfigureOrder来调整优先级

2.4 配置文件信息绑定到java对象  @ConfigurationProperties

将配置信息绑定到对应java对象上

 

 

参考:

https://blog.csdn.net/m0_46628950/article/details/125469964

posted on 2022-01-17 10:41  colorfulworld  阅读(2148)  评论(0)    收藏  举报