spring boot 註解在啓動的時候作了什麼

##Spring 註解##java

在springboot環境中,只須要寫一個main方法再加上***@SpringBootApplication***,運行main方法就能啓動服務器了,那它究竟是怎麼工做的?web

探究一下spring boot裏面註解是怎麼工做的spring

1.Spring Boot的啓動過程

註解的加載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方法。

輸入圖片說明

prepareContext加載客戶代碼

這一塊是加載客戶代碼。拿到代碼標註註解的實際處理器

// 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必需組件的加載

二、客戶端代碼的加載

2.Spring 客戶端代碼加載

在上述啓動成功後,客戶端的組件經過@SpringBootConfiguration@EnableAutoConfiguration加載到容器中,它們的註解處理器在第一步已經聲明瞭。

相關文章
相關標籤/搜索