##Spring 註解##java
在springboot環境中,只須要寫一個main方法再加上***@SpringBootApplication***,運行main方法就能啓動服務器了,那它究竟是怎麼工做的?web
探究一下spring boot裏面註解是怎麼工做的spring
註解的加載springboot
按照Spring Boot啓動的一步一步分析,最主要的是進到這個方法。服務器
public ConfigurableApplicationContext run(String... args) { // 省下部分代碼,如下代碼是將一些必要的組件加載到容器中 context = createApplicationContext(); //....... return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContextapp
//經過反射生成ApplicationContext對象,返回的對象實例是: //org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext 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); }
進到AnnotationConfigEmbeddedWebApplicationContext的構造方法post
public AnnotationConfigEmbeddedWebApplicationContext() { //看字面意思是,將聲明的註解加載到容器中 this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
早AnnotatedBeanDefinitionReader類中,ui
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); }
最終起做用的是 registerAnnotationConfigProcessors,從註釋中能夠看到他會將與**registry(AnnotationConfigEmbeddedWebApplicationContext)**相關的註解加載到容器裏面,this
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { registerAnnotationConfigProcessors(registry, null); } /** * Register all relevant annotation post processors in the given registry. * @param registry the registry to operate on * @param source the configuration source element (already extracted) * that this registration was triggered from. May be {@code null}. * @return a Set of BeanDefinitionHolders, containing all bean definitions * that have actually been registered by this call */ public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
上面的方法的做用是,判斷幾個關鍵的註解處理器是否存在容器中,若是不存在,則將對應的處理器添加到容器裏面。lua
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)); }
這些處理類分別是:
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"; public static final String CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator"; public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"; public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalRequiredAnnotationProcessor"; public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalCommonAnnotationProcessor"; public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalPersistenceAnnotationProcessor"; private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME = "org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"; /** * The bean name of the internally managed @EventListener annotation processor. */ public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME = "org.springframework.context.event.internalEventListenerProcessor"; /** * The bean name of the internally managed EventListenerFactory. */ public static final String EVENT_LISTENER_FACTORY_BEAN_NAME = "org.springframework.context.event.internalEventListenerFactory"; private static final boolean jsr250Present = ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader()); private static final boolean jpaPresent = ClassUtils.isPresent("javax.persistence.EntityManagerFactory", AnnotationConfigUtils.class.getClassLoader()) && ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader());
進行上面操做後,添加了以下的註解處理器到容器中了
result = {LinkedHashSet@2388} size = 6 0 = {DelegatingApplicationContextInitializer@2349} 1 = {ContextIdApplicationContextInitializer@2350} 2 = {ConfigurationWarningsApplicationContextInitializer@2351} 3 = {ServerPortInfoApplicationContextInitializer@2352} 4 = {SharedMetadataReaderFactoryContextInitializer@2353} 5 = {AutoConfigurationReportLoggingInitializer@2354}
以上的步驟是將spring boot(SpringApplication類)運行所須要的組件加載到容器中,這一步完成後。加載用戶所寫的main方法。
這一塊是加載客戶代碼。拿到代碼標註註解的實際處理器
// Load the sources //返回springboot的啓動類 Set<Object> sources = getSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[sources.size()])); listeners.contextLoaded(context);
將啓動類加載到容器中
其中框紅的部分是經過BeanDefinitionLoader 來獲取啓動類中用到註解的處理器。
這樣就這個容器的啓動接完成了,總的來講,spring boot的啓動分爲兩個部分。
一、spring boot必需組件的加載
二、客戶端代碼的加載
在上述啓動成功後,客戶端的組件經過@SpringBootConfiguration@EnableAutoConfiguration加載到容器中,它們的註解處理器在第一步已經聲明瞭。