本文基于springboot1.5.4版本。
在springboot的世界中,有一个非常神奇的注解@SpringBootApplication,这个注解可以一键把你的工程变成springboot工程。
下面我们来看下它的源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication
可以看出,SpringBootApplication是一个复合注解,其中重要的注解有ComponentScan,
EnableAutoConfiguration和SpringBootConfiguration。其中SpringBootConfiguration其实是Configuration的简单封装,两者等价。
使用上述三个注解代替@SpringBootApplication后,应用可以正常启动成功,完美!
Configuration
这个注解其实是spring的注解了,作用是替代xml格式的spring配置,不过多解释了。
ComponentScan
xml配置
EnableAutoConfiguration
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration
这个是springboot的灵魂。EnableAutoConfiguration主要通过EnableAutoConfigurationImportSelector来实现具体功能。
主要作用如下:
1.通过SpringFactoriesLoader辅助类加载所有jar包里的/META-INF/spring.factories文件,
查找其中的key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的value。(其原理类似于java.util.ServiceLoader
2.然后通过Conditonal下的一系列注解来过滤这些value中的类应不应该被加载。
例如ConditionalOnClass/ConditionalOnProperty等。
不过我有几个疑问一直没找到答案:
1.Spring是如何处理这种复合注解的,如何识别一个注解上面还有其它的注解?
2.ConditionalOnClass等条件的过滤是通过加载解析/META-INF/spring-autoconfigure-metadata.properties文件实现的,这个文件是自动解析类上的注解生成的吗,还是需要手动写?
第一个疑问
写了一段代码模拟spring解析annotation的操作:
@Test
public void testAnno(){
TestAnno testAnno =new TestAnno();
Class aClass = testAnno.getClass();
//or this way
// aClass = TestAnno.class;
Set set =new HashSet();
for (Annotation annotation : aClass.getAnnotations()) {
add2SetIter(set, annotation);
}
System.out.println(set);
}
private void add2SetIter(Set set, Annotation annotation) {
set.add(annotation);
for (Annotation annotation1 : annotation.annotationType().getAnnotations()) {
if (BLACKLIST.contains(annotation1.annotationType())){
continue;
}
add2SetIter(set, annotation1);
}
}
private static final List>BLACKLIST = Arrays.asList(Documented.class,Retention.class,Target.class);
第二个疑问
添加以下依赖后,编译打包时会自动生成spring-autoconfigure-metadata.properties
org.springframework.boot
spring-boot-configuration-processor
true
2018-08-26更新,第一个疑问的答案
org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.Class>, java.lang.Class)