@SpringBootApplication原理
@SpringBootApplication//标记这是一个主程序类,说明这是一个springboot应用
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
进入@SpringBootApplication注解,会发现里面有三个关键的注解
@springbootconfiguration
@enableautoconfiguration
@componentScan
我们就开始分析一下这三个注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
①:@springbootconfiguration
springboot配置注解,我们点进去就会发现,里面是一个@configuration注解,再点进去,就会发现@Component,所以很明显,这是一个配置类的注解,里面就是他的组件。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
----------------------------------------------------
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(
annotation = Component.class
)
String value() default "";
boolean proxyBeanMethods() default true;
}
②:@componentScan
自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中。
③:@EnableAutoConfiguration(重点)
springboot的核心是什么,就是自动装配,为什么springboot会简化开发,就是它省去了大量的之前我们需要配置的文件,而我们不用配,那总有人会帮你配,那就是springboot,springboot已经自动帮我们装配好了我们需要配置的文件。那么我们就来探究一下这个@EnableAutoConfiguration是怎么帮我们实现自动装配的。
@EnableAutoConfiguration(自动配置),我们点开这个注解,会发现有两个关键的注解
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage(自动配置包),再点开这个注解就会看到这个注解
@Import(AutoConfigurationPackages.Registrar.class)
它导入了自动配置包注册,注册的是哪的包,就是我们@component注解扫描出来的包,所以这个注解的功能我们就看到这,接下来我们回到@Import(AutoConfigurationImportSelector.class)这个注解。
@Import(AutoConfigurationImportSelector.class)导入了AutoConfigurationImportSelector(自动配置导入搜索器)这个类,我们就打开这个类看一下。
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
----------------------------------------------------------------
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
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;
}
我们看到这个方法getAutoConfigurationEntry(),获取自动配置实例,而它是调用的getCandidateConfigurations()这个方法获得的configuration,而getCandidateConfigurations()中是调用的loadFactoryNames这个方法
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
那我们就点开这个方法看看是怎么获得的。
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
然后我们又看到了这样一个方法loadSpringFactories,这个方法里面就会有我们的关键部分
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
String[] var10 = factoryImplementationNames;
int var11 = factoryImplementationNames.length;
for(int var12 = 0; var12 < var11; ++var12) {
String factoryImplementationName = var10[var12];
((List)result.computeIfAbsent(factoryTypeName, (key) -> {
return new ArrayList();
})).add(factoryImplementationName.trim());
}
}
}
我们可以看到类加载器加载了(“META-INF/spring.factories”)这个路径下的资源,然后一系列的循环遍历得到了结果,所以,答案应该就在META-INF/spring.factories这个路径下,我们找到这个文件,并打开。
我们可以看到全部都是一些类路径的全限定名,并且基本上后缀都是xxxAutoConfiguration,我们就可以猜想,这些就是自动配置类,我们带着这个猜想,打开一个看看。
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
/**
* The default Spring MVC view prefix.
*/
public static final String DEFAULT_PREFIX = "";
/**
* The default Spring MVC view suffix.
*/
public static final String DEFAULT_SUFFIX = "";
private static final String SERVLET_LOCATION = "/";
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
@Bean
@ConditionalOnMissingBean(FormContentFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.formcontent.filter", name = "enabled", matchIfMissing = true)
public OrderedFormContentFilter formContentFilter() {
return new OrderedFormContentFilter();
}
点开之后,会发现有一个注解@Configuration(proxyBeanMethods = false),这就很清楚了,这就是一个java配置类,下面的@Bean就是它的一个个组件。