1.什么是springboot自動配置:Auto-Configuration
自動配置值得是基於引入依賴的jar包,對springboot應用進行自動配置。自動配置為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; } }
直接用以上三步就可以在springboot中使用mongo,整個過程springboot自動完成mongo配置,將相關對象注入到IOC容器中 (面試問IOC時候可以從這個角度回答)
2.默認自動配置類
Springboot通過自動配置可以自動加載一些需要的配置信息,引入了一個依賴:spring-boot-autoconfigure,其中定義了大量自動配置類
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
2.自動配置實現原理
@EnableAutoConfiguration:開啟SpringBoot的自動配置,並且根據你引入的依賴來生效對應的默認配置(在springboot中不需要手動添加這個注解)
@Conditional :可以標注在類上面,表示該類下面的所有@Bean都會啟用配置,也可以標注在方法上面,只是對該方法啟用配置。
@ConditionalOnBean(僅僅在當前上下文中存在某個對象時,才會實例化一個Bean)
@ConditionalOnClass(某個class位於類路徑上,才會實例化一個Bean)
@ConditionalOnExpression(當表達式為true的時候,才會實例化一個Bean)
@ConditionalOnMissingBean(僅僅在當前上下文中不存在某個對象時,才會實例化一個Bean)
@ConditionalOnMissingClass(某個class類路徑上不存在的時候,才會實例化一個Bean)
@ConditionalOnNotWebApplication(不是web應用)
示例代碼:
Config類: package com.fql.example.project.autoconfig.config; import com.fql.example.project.autoconfig.service.TestService; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /**https://blog.csdn.net/wolf2s/article/details/122260211 * Created by Administrator on 2022/1/15 0015. */ @Configuration @Slf4j public class TestStartServiceConfig { @Bean @ConditionalOnBean(TestService.class) //--1 //@ConditionalOnMissingBean(TestService.class) //--2 public TestService getTestService(){ log.info("this is a testStartService"); return new TestService(); } } Service類: package com.fql.example.project.autoconfig.service; /** * Created by Administrator on 2022/1/16 0016. */ public class TestService { } Application類: package com.fql.example.project; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.servlet.DispatcherServlet; @SpringBootApplication public class ProjectApplication { public static void main(String[] args) { SpringApplication.run(ProjectApplication.class, args); } }
TestStartServiceConfig中設置為@ConditionalOnBean(TestService.class)輸出如下:
2022-01-17 10:36:38.421 INFO 1084 --- [ main] c.f.example.project.ProjectApplication : Starting ProjectApplication using Java 1.8.0_221 on PC-20190113KYFH with PID 1084 (D:\java\fqldemo\project\target\classes started by Administrator in D:\java\fqldemo\project)
2022-01-17 10:36:38.428 INFO 1084 --- [ main] c.f.example.project.ProjectApplication : No active profile set, falling back to default profiles: default
2022-01-17 10:36:39.946 INFO 1084 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-01-17 10:36:39.957 INFO 1084 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-01-17 10:36:39.957 INFO 1084 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-17 10:36:40.070 INFO 1084 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-01-17 10:36:40.070 INFO 1084 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1567 ms
2022-01-17 10:36:40.483 INFO 1084 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-17 10:36:40.497 INFO 1084 --- [ main] c.f.example.project.ProjectApplication : Started ProjectApplication in 2.649 seconds (JVM running for 3.319)
從控制台輸出可以發現沒有看到TestStartServiceConfig中打印log.info("this is a testStartService");這是因為TestStartService沒有實例化,如果我們把TestService改為
@Service
public class TestService {
}
那么輸出如下:
2022-01-17 10:39:01.381 INFO 8436 --- [ main] c.f.example.project.ProjectApplication : Starting ProjectApplication using Java 1.8.0_221 on PC-20190113KYFH with PID 8436 (D:\java\fqldemo\project\target\classes started by Administrator in D:\java\fqldemo\project)
2022-01-17 10:39:01.386 INFO 8436 --- [ main] c.f.example.project.ProjectApplication : No active profile set, falling back to default profiles: default
2022-01-17 10:39:02.956 INFO 8436 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-01-17 10:39:02.967 INFO 8436 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-01-17 10:39:02.967 INFO 8436 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-17 10:39:03.085 INFO 8436 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-01-17 10:39:03.085 INFO 8436 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1618 ms
2022-01-17 10:39:03.154 INFO 8436 --- [ main] c.f.e.p.a.config.TestStartServiceConfig : this is a testStartService
2022-01-17 10:39:03.465 INFO 8436 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-17 10:39:03.475 INFO 8436 --- [ main] c.f.example.project.ProjectApplication : Started ProjectApplication in 2.669 seconds (JVM running for 3.348)
TestStartServiceConfig中設置為@ConditionalOnMissingBean(TestService.class)輸出如下
2022-01-17 10:39:01.381 INFO 8436 --- [ main] c.f.example.project.ProjectApplication : Starting ProjectApplication using Java 1.8.0_221 on PC-20190113KYFH with PID 8436 (D:\java\fqldemo\project\target\classes started by Administrator in D:\java\fqldemo\project)
2022-01-17 10:39:01.386 INFO 8436 --- [ main] c.f.example.project.ProjectApplication : No active profile set, falling back to default profiles: default
2022-01-17 10:39:02.956 INFO 8436 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-01-17 10:39:02.967 INFO 8436 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-01-17 10:39:02.967 INFO 8436 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-17 10:39:03.085 INFO 8436 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-01-17 10:39:03.085 INFO 8436 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1618 ms
2022-01-17 10:39:03.154 INFO 8436 --- [ main] c.f.e.p.a.config.TestStartServiceConfig : this is a testStartService
2022-01-17 10:39:03.465 INFO 8436 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-17 10:39:03.475 INFO 8436 --- [ main] c.f.example.project.ProjectApplication : Started ProjectApplication in 2.669 seconds (JVM running for 3.348)
當然在這種情況下如果,把改為
@Service
public class TestService {
}
,則 this is a testStartService不會打印,具體輸出如下
2022-01-17 10:41:05.079 INFO 8632 --- [ main] c.f.example.project.ProjectApplication : Starting ProjectApplication using Java 1.8.0_221 on PC-20190113KYFH with PID 8632 (D:\java\fqldemo\project\target\classes started by Administrator in D:\java\fqldemo\project)
2022-01-17 10:41:05.083 INFO 8632 --- [ main] c.f.example.project.ProjectApplication : No active profile set, falling back to default profiles: default
2022-01-17 10:41:06.732 INFO 8632 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-01-17 10:41:06.744 INFO 8632 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-01-17 10:41:06.744 INFO 8632 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-17 10:41:06.917 INFO 8632 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-01-17 10:41:06.917 INFO 8632 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1747 ms
2022-01-17 10:41:07.290 INFO 8632 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-17 10:41:07.300 INFO 8632 --- [ main] c.f.example.project.ProjectApplication : Started ProjectApplication in 2.797 seconds (JVM running for 3.472)
補充:
@ConfigurationProperties
使用了@ConfigurationProperties配置之后,可以進一步簡化@Value()的使用,最后的結果會變成這個簡單
@Configuration
@Data
@Immutable
@ConfigurationProperties(prefix = "spring.kafka")
public class KafkaTopicConfig {
private String errorTopic;
private String successTopic;
}
等價於
@Configuration
@Data
@Immutable
public class KafkaTopicConfig {
@Value("${spring.profiles.errorTopic}")
private String errorTopic;
@Value("${spring.profiles.successTopic}")
private String successTopic;
}
參考:
https://blog.csdn.net/m0_46628950/article/details/125469964