Spring注解@Configuration是如何被处理的?
从SpringApplication开始
一般情况下启动SpringBoot都是新建一个类包含main
方法,然后使用SpringApplication.run
来启动程序:
@SpringBootApplication public class AutoConfigApplication { public static void main(String[] args){ ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(AutoConfigApplication.class,args); } }
SpringApplication.run
接收两个参数分别为:primarySource、运行参数(args),上面的代码使用AutoConfigApplication.class
作为primarySource。SpringApplication还有一个实例方法也叫run
,SpringBoot的大部分启动都由实例run
方法来完成的,其中构造ApplicationContext由createApplicationContext
方法完成:
protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch (this.webApplicationType) { case SERVLET: contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; case REACTIVE: contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); }
createApplicationContext
根据this.webApplicationType
来构造ApplicationContext,不同的环境都会使用不同的实例,但本文非web环境所有构造的时候会使用AnnotationConfigApplicationContext
类。创建AnnotationConfigApplicationContext
的时候会调用默认构造方法
:
public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
AnnotationConfigApplicationContext默认构造函数创建两个对象:
- reader(AnnotatedBeanDefinitionReader):用于手动注册bean
- scanner(ClassPathBeanDefinitionScanner): 用于扫描Component、Repository、Service等注解
AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner会注册一些注解处理器,注册的方式都是使用AnnotationConfigUtils的registerAnnotationConfigProcessors方法: