Spring boot为了自动配置,增加了注解@EnableAutoConfiguration
。一般只需要配置@SpringBootApplication
即可,为什么呢?
@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 {
很明显的,这个注解就是三个常用的注解@SpringBootConfiguration
,@EnableAutoConfiguration
以及@ComponentScan
组合在一起。
@SpringBootConfiguration
这个注解实际上和@Configuration
有相同的作用,配备了该注解的类就能够以JavaConfig的方式完成一些配置,可以不再使用XML配置。
@ComponentScan
这个注解完成的是自动扫描的功能,相当于Spring XML配置文件中的:
,可以使用basePackages属性指定要扫描的包,以及扫描的条件。如果不设置的话默认扫描@ComponentScan
注解所在类的同级类和同级目录下的所有类,所以对于一个Spring Boot项目,一般会把入口类放在顶层目录中,这样就能够保证源码目录下的所有类都能够被扫描到。
@EnableAutoConfiguration
注解代码如下:
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
这个注解是让Spring Boot的配置能够如此简化的关键性注解。那么这个注解到底是怎么生效的呢?
在SpringApplication的run方法中,会调用context = createApplicationContext();
protected ConfigurableApplicationContext createApplicationContext() {
Class> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
这里的DEFAULT_WEB_CONTEXT_CLASS值是org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext
,DEFAULT_CONTEXT_CLASS值是org.springframework.context.annotation.AnnotationConfigApplicationContext
。在实例化它们的时候都会实例化一个AnnotatedBeanDefinitionReader。例如AnnotationConfigEmbeddedWebApplicationContext实例化代码:
public AnnotationConfigEmbeddedWebApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
这里将构造AnnotatedBeanDefinitionReader,在AnnotatedBeanDefinitionReader实例化过程中,会向beanFactory注册CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor、ConfigurationClassPostProcessor等:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
public static Set registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set beanDefs = new LinkedHashSet(4);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
也就是说createApplicationContext()
完后,beanFactory的beanDefinitionMap会有6个值。
SpringApplication的run方法中,在调用createApplicationContext();
后会调用prepareContext(context, environment, listeners, applicationArguments,printedBanner)
:
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// …略
// Load the sources
Set
getSources()
返回的就是new SpringApplication(Application.class)
传入的参数,即Application.class,然后调用了load()
方法,在load()
中会生成BeanDefinitionLoader实例,并把主类Application.class注册到IOC容器中。
OK,到这里即在调用熟悉的AbstractApplicationContext#refresh()
前,beanFactory有7个定义好的beanDefinition。
ConfigurationClassPostProcessor是BeanFactoryPostProcessor的子类,会在Spring容器refresh时,invokeBeanFactoryPostProcessors(beanFactory)
方法中调用到。ConfigurationClassPostProcessor会解析到我们的主类,把@Import
中的类拿出来,调用它的selectImports()
方法。
而在AutoConfigurationImportSelector
类中:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
getCandidateConfigurations
方法就会在META-INF/spring.factories
中找到获取约定好的自动配置类(key为EnableAutoConfiguration的value)。然后Spring容器会对这些配置类进行处理。
到此,一目了然,由ConfigurationClassPostProcessor来处理。@ComponentScan
注解也是在ConfigurationClassPostProcessor中处理的。