1. Spring部分注解
- @Import : 為Spring容器中引入一些組件,通常都有無參數(shù)的構(gòu)造方法
- @ConditionXXX : 需要達(dá)成某些條件該配置類才會(huì)生效
- @EnableAutoConfiguration : 開啟自動(dòng)配置注解,在@SpringBootApplication注解中已經(jīng)開啟
2. 自動(dòng)裝配過程
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
- 通過
@Import(EnableAutoConfigurationImportSelector.class)
引入了這個(gè)類
- 這個(gè)類的父類有一個(gè)
selectImports
的方法,這個(gè)方法里面有一個(gè)List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);
來獲取到所有的候選配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
/** 這個(gè)方法來獲取所有的配置,getSpringFactoriesLoaderFactoryClass()方法是EnableAutoConfiguration.class; */
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), 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;
}
- 再點(diǎn)進(jìn)去
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
/** 去掃描所有包的WEB-INF/spring.factory文件,得到他們的路徑 */
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
/** 然后加載這個(gè)properties文件,獲取到key為EnableAutoConfiguration.class的值,實(shí)際上就是很多的XXXAutoConfiguration配置類 */
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
- 加載這些配置類到Spring容器中,而這些配置類的作用,就是為容器中添加各種各樣的組件,就完成了自動(dòng)裝配的作用,其中一個(gè)配置類如下:
@Configuration
/** 加載這個(gè)類到這個(gè)配置類中,是一些屬性 */
@EnableConfigurationProperties(HttpEncodingProperties.class)
/** 必須是一個(gè)web項(xiàng)目才會(huì)加載這個(gè)配置類 */
@ConditionalOnWebApplication
@ConditionalOnClass(CharacterEncodingFilter.class)
/** 配置文件中有spring.http.encoding開頭的也加載進(jìn)來,如果沒有匹配到,也可以加載這個(gè)類 */
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
private final HttpEncodingProperties properties;
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}
/** @Bean,為容器中添加組件 */
@Bean
@ConditionalOnMissingBean(CharacterEncodingFilter.class)
public CharacterEncodingFilter characterEncodingFilter() {
3 我們?nèi)绾问褂肧pringBoot
- 添加 spring-boot-xxx-starter包
- 查看對(duì)應(yīng)的AutoConfiguration配置類,和對(duì)應(yīng)的xxxPropertise文件
- 如果不滿意默認(rèn)配置,我們就進(jìn)行配置,按照他的規(guī)范
- 容器中有了對(duì)應(yīng)的組件,我們還可以在自己的Confuration類中對(duì)這些組件進(jìn)行進(jìn)一步包裝.