1.SpringBoot自動(dòng)配置原理
從@SpringBootApplication注解開(kāi)始說(shuō)沧竟,這個(gè)注解是一個(gè)復(fù)合注解铸敏,他是由以下幾個(gè)注解構(gòu)成的。
// 用于講其他配置類(lèi)悟泵,注入到spring ioc中的
@SpringBootConfiguration
// 自動(dòng)配置最重要的注解
@EnableAutoConfiguration
// 用于掃描其他注解(@service杈笔、@controller)等等
@ComponentScan(
? ? excludeFilters = {@Filter(
? ? type = FilterType.CUSTOM,
? ? classes = {TypeExcludeFilter.class}
), @Filter(
? ? type = FilterType.CUSTOM,
? ? classes = {AutoConfigurationExcludeFilter.class}
)}
)
記得點(diǎn)贊收藏加關(guān)注哦 ,需要下載PDF版本和獲取更多知識(shí)點(diǎn)糕非、面試題的朋友可以加q群:580763979? ?備注:簡(jiǎn)書(shū)? ?免費(fèi)領(lǐng)取~
接下來(lái)從@EnableAutoConfiguration開(kāi)始講起
其中關(guān)鍵的地方就是這個(gè)AutoConfigurationImportSelector類(lèi)
@Import({AutoConfigurationImportSelector.class})
他里面的selectImports方法中g(shù)etAutoConfigurationEntry就是獲取自動(dòng)配置的重要組成
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
? ? return NO_IMPORTS;
} else {
? ? AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
? ? return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
? ? return EMPTY_ENTRY;
} else {
? ? AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
? ? List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
? ? configurations = this.removeDuplicates(configurations);
? ? Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
? ? this.checkExcludedClasses(configurations, exclusions);
? ? configurations.removeAll(exclusions);
? ? configurations = this.getConfigurationClassFilter().filter(configurations);
? ? this.fireAutoConfigurationImportEvents(configurations, exclusions);
? ? return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
通過(guò)上述獲取在META-INF/spring.factories蒙具,
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;
}
在spring.factories中會(huì)存在很多這樣的鍵值對(duì)
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
當(dāng)springboot啟動(dòng)的時(shí)候就會(huì)加載這些xxxAutoConfigureation,這里以RedisAutoConfiguration為例朽肥,介紹是如何進(jìn)行配置的禁筏。
// 只有符合這種要求的,才會(huì)將xxxAutoConfigureation加載到spring中
@ConditionalOnClass({RedisOperations.class})
// 開(kāi)啟配置類(lèi)
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
RedisProperties配置類(lèi)衡招,看到這個(gè)類(lèi)篱昔,是不是很熟悉,他就是我們?cè)趛ml里面配置的東西
@ConfigurationProperties(
? ? prefix = "spring.redis"
)
public class RedisProperties {
? ? private int database = 0;
? ? private String url;
? ? private String host = "localhost";
? ? private String username;
? ? private String password;
? ? private int port = 6379;
? ? private boolean ssl;
? ? private Duration timeout;
? ? private Duration connectTimeout;
? ? private String clientName;
}
總結(jié):通過(guò)上述流程實(shí)現(xiàn)將快速配置蚁吝,減少了繁瑣的xml配置旱爆,如果要配置,只需簡(jiǎn)單的在yml配置即可窘茁。
2.自定義starter怀伦,簡(jiǎn)單實(shí)現(xiàn)一個(gè)線程池的創(chuàng)建
創(chuàng)建一個(gè)thread-pool-execute-starter的工程
// 添加依賴
<groupId>com.angel.item</groupId>
<artifactId>thread-pool-execute-starter</artifactId>
<version>1.0</version>
<dependencies>
? ? <dependency>
? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? <artifactId>spring-boot-starter</artifactId>
? ? </dependency>
</dependencies>
自動(dòng)配置類(lèi)
@Configuration
// 配置配置屬性
@EnableConfigurationProperties(ThreadPoolExecutorProperties.class)
// 只有這個(gè)類(lèi)才會(huì)生校
@ConditionalOnClass(ThreadPoolExecutor.class)
public class ThreadPoolAutoConfiguration {
? ? /**
? ? * 阻塞隊(duì)列
? ? */
? ? private final BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(4);
? ? /**
? ? * 拒絕策略
? ? */
? ? private final RejectedExecutionHandler reject = new ThreadPoolExecutor.AbortPolicy();
? ? /**
? ? * 線程池類(lèi)型:CPU密集型:1;IO密集型:2
? ? */
? ? @Value("${scenes}")
? ? private Integer scenes;
? ? /**
? ? * 核心線程數(shù)大小
? ? */
? ? private Integer corePoolSize;
? ? /**
? ? * 最大線程數(shù)大小
? ? */
? ? private Integer maximumPoolSize;
? ? /**
? ? * 空閑線程存活時(shí)長(zhǎng)
? ? */
? ? private Long keepAliveTime;
? ? /**
? ? * 存活時(shí)長(zhǎng)單位
? ? */
? ? private TimeUnit unit;
? ? @PostConstruct
? ? public void init() {
? ? ? ? // 獲取系統(tǒng)CPU核心數(shù)
? ? ? ? int cpuCoreNumber = Runtime.getRuntime().availableProcessors();
? ? ? ? this.corePoolSize = cpuCoreNumber;
? ? ? ? this.maximumPoolSize = 25 * cpuCoreNumber;
? ? ? ? this.keepAliveTime = 60 * 3L;
? ? ? ? this.unit = TimeUnit.SECONDS;
? ? }
? ? /**
? ? * N: CPU核心數(shù)
? ? * CPU密集型:corePoolSize = N + 1
? ? * IO密集型:corePoolSize = 2 * N
? ? */
? ? @Bean
? ? public ThreadPoolExecutor threadPoolExecutor() {
? ? ? ? // cpu密集型
? ? ? ? if (scenes == 1) {
? ? ? ? ? ? corePoolSize = corePoolSize + 1;
? ? ? ? } else {
? ? ? ? ? ? // io密集型
? ? ? ? ? ? corePoolSize = 2 * corePoolSize;
? ? ? ? }
? ? ? ? return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, reject);
? ? }
}
配置類(lèi)屬性
@ConfigurationProperties(
? ? ? ? prefix = "thread.pool"
)
public class ThreadPoolExecutorProperties {
? ? private Integer scenes = 1;
? ? public Integer getScenes() {
? ? ? ? return scenes;
? ? }
? ? public void setScenes(Integer scenes) {
? ? ? ? this.scenes = scenes;
? ? }
}
在resources中新建META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.angel.item.ThreadPoolAutoConfiguration
將工程重新打包山林,mvn clean install -U
在另外的工程中引入上面的坐標(biāo)
<dependency>
? ? <groupId>com.angel.item</groupId>
? ? <artifactId>thread-pool-execute-starter</artifactId>
? ? <version>1.0</version>
</dependency>
在yml配置即可
thread:
? pool:
? ? scenes: 1
mvn package 重新打包
總結(jié):通過(guò)上述配置自定義starter就可以實(shí)現(xiàn)了
我這里也準(zhǔn)備了一線大廠面試資料和超硬核PDF技術(shù)文檔房待,以及我為大家精心準(zhǔn)備的多套簡(jiǎn)歷模板(不斷更新中)邢羔,希望大家都能找到心儀的工作!
有需要的朋友可以加q群:580763979? ?備注:簡(jiǎn)書(shū)? ?免費(fèi)領(lǐng)取~