spring boot 注解在启动的时候做了什么

##Spring 注解##

在springboot环境中,只需要写一个main方法再加上***@SpringBootApplication***,运行main方法就能启动服务器了,那它到底是怎么工作的?

探究一下spring boot里面注解是怎么工作的

1.Spring Boot的启动过程

注解的加载

按照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.AnnotationConfigEmbeddedWebApplicationContext

//通过反射生成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的构造方法

	public AnnotationConfigEmbeddedWebApplicationContext() {
      	//看字面意思是,将声明的注解加载到容器中
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

早AnnotatedBeanDefinitionReader类中,

	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)**相关的注解加载到容器里面,

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(

上面的方法的作用是,判断几个关键的注解处理器是否存在容器中,如果不存在,则将对应的处理器添加到容器里面。

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的启动分为两个部分。

1、spring boot必需组件的加载

2、客户端代码的加载

2.Spring 客户端代码加载

在上述启动成功后,客户端的组件通过@SpringBootConfiguration@EnableAutoConfiguration加载到容器中,它们的注解处理器在第一步已经声明了。

转载于:https://my.oschina.net/u/3711426/blog/1816730

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值