目录
版本
版本:3.0.1
注解
我们从启动类入手,springboot的启动类上要添加 @SpringBootApplication
注解,我们先看一下这个注解的作用:
@SpringBootApplication
//用于描述类、接口(包括注解类型) 或enum声明
@Target({ElementType.TYPE})
//注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
@Retention(RetentionPolicy.RUNTIME)
//表明这个注解应该被 javadoc工具记录
@Documented
//子类将会继承该注解
@Inherited
//相当于@Configuration
@SpringBootConfiguration
//启用 SpringBoot 的自动配置机制
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
//使用Import自动导入所有符合自动配置条件的Bean定义并加载到IOC容器
@Import(AutoConfigurationImportSelector.class)
这个注解里面比较引人注意的是这两个注解:
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
介绍
三种将类交给spring管理,也就是加入IOC容器的方式:
- @Bean
- @Componet/@Service
- @Import
@Import一般作用于@Configuration定义的类上,它有三种用法
先假设我们有3个类
public class Apple {
}
public class Banana {
}
public class Cherry {
}
都通过这个类注入:
@Configuration
public class Fruits {
}
指定class数组方式
@Configuration
@Import(Apple.class)
public class Fruits {
}
ImportSelector方式(Spring Boot底层采用比较得多的方式)
public class BananaImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.test.Banana"};
}
}
@Configuration
@Import({Apple.class,BananaImportSelector.class})
public class Fruits {
}
ImportBeanDefinitionRegistrar方式
public class CherryDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition=new RootBeanDefinition(Cherry.class);
//这里还可以给Cherry这个类改个名字,比如Coconut
registry.registerBeanDefinition("Coconut",rootBeanDefinition);
}
}
@Configuration
@Import({Apple.class,BananaImportSelector.class,CherryDefinitionRegistrar.class})
public class Fruits {
}
正题
以上,也就是说,在这个地方,要先引入一些类,而且是通过第二种方式来进行的,我们看下这个类:AutoConfigurationImportSelector.class
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//判断EnableAutoConfiguration是否开启,一般默认开启的
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
//这里又判断了一遍EnableAutoConfiguration是否开启
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//这里可以理解为获取到了EnableAutoConfiguration的属性和我们传入的值。
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//这里可以理解为获取到了所有可以自动注入的类名
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//给这些需要自动注入的类名去重,通过list-set-list的方式
configurations = removeDuplicates(configurations);
//把我们设置了排出的整个set返回回来
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//验证一下要排除自动的类是否合法,不合法的话会直接抛异常
checkExcludedClasses(configurations, exclusions);
//这里就直接把我们想要排除的类从自动启动里都remove了
configurations.removeAll(exclusions);
//TODO:这块另写一篇 获取过滤器,过滤配置类
configurations = getConfigurationClassFilter().filter(configurations);
//TODO:这块另写一篇 获取所有的AutoConfigurationImportListener类型的监听器。然后广播AutoConfigurationImportEvent事件
fireAutoConfigurationImportEvents(configurations, exclusions);
//配置类名字结合和排除集合封装成AutoConfigurationEntry返回
return new AutoConfigurationEntry(configurations, exclusions);
}
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
//拿到了EnableAutoConfiguration类的名字
String name = getAnnotationClass().getName();
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
Assert.notNull(attributes, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()
+ " annotated with " + ClassUtils.getShortName(name) + "?");
return attributes;
}
protected final <T> List<T> removeDuplicates(List<T> list) {
return new ArrayList<>(new LinkedHashSet<>(list));
}
private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
List<String> invalidExcludes = new ArrayList<>(exclusions.size());
for (String exclusion : exclusions) {
if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) {
invalidExcludes.add(exclusion);
}
}
if (!invalidExcludes.isEmpty()) {
handleInvalidExcludes(invalidExcludes);
}
}
private ConfigurationClassFilter getConfigurationClassFilter() {
if (this.configurationClassFilter == null) {
//这里其实获取到了AutoConfigurationImportFilter
List<AutoConfigurationImportFilter> filters = getAutoConfigurationImportFilters();
for (AutoConfigurationImportFilter filter : filters) {
invokeAwareMethods(filter);
}
this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);
}
return this.configurationClassFilter;
}
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
if (!listeners.isEmpty()) {
//这块主要是获取到了AutoConfigurationImportFilter的三个实现类
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
for (AutoConfigurationImportListener listener : listeners) {
invokeAwareMethods(listener);
listener.onAutoConfigurationImportEvent(event);
}
}
}
protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
}
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
if (!listeners.isEmpty()) {
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
for (AutoConfigurationImportListener listener : listeners) {
invokeAwareMethods(listener);
listener.onAutoConfigurationImportEvent(event);
}
}
}
protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
}
参考
SpringBoot之@EnableAutoConfiguration注解
SpringBootApplication-@Import(AutoConfigurationImportSelector.class)