自动装配-浅谈SpringBoot

SpringBoot vsersion 2.2.6

1. SpringApplication.run(Application.class, args);

从这个方法为研究对象

1.1 @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 {
	...

@SpringBootApplication包含了三个个重要注解@SpringBootConfiguration和@EnableAutoConfiguration @ComponentScan

1.2 @SpringBootConfiguration

底层是@Configuration注解
@Configuration 当前类当成一个配置类 相当于一个Beans标签 可以用@Bean配合该注解 声明多个Bean到IOC容器里

1.3 @EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	// isEnabled用到了这个变量 去environment拿这个key值的value
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
	...
protected boolean isEnabled(AnnotationMetadata metadata) {
	if (getClass() == AutoConfigurationImportSelector.class) {
		return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
	}
	return true;
}

@AutoConfigurationPackage 该注解导入了一个@Import(AutoConfigurationPackages.Registrar.class)注册扫描路径到全局变量
@Import(AutoConfigurationImportSelector.class)

1.4 AutoConfigurationImportSelector

selectImports -> getAutoConfigurationEntry

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		//spring.boot.enableautoconfiguration environment里的这个key值为false 返回空
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		// 获取注解的属性值
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		// 获取spring.factories里的 org.springframework.boot.autoconfigure.EnableAutoConfiguration的value集合名称
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		// 去重
		configurations = removeDuplicates(configurations);
		// 收集排除的类名
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		// 去排除的数据
		configurations.removeAll(exclusions);
		// 由所有AutoConfigurationImportFilter类的实例再进行一次筛选
		configurations = filter(configurations, autoConfigurationMetadata);
		// 绑定事件
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}
}

重点: starter原理
selectImports -> getAutoConfigurationEntry -> getCandidateConfigurations

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	// 相当于Spring的SPI 约定META-INF/spring.factories 读取里面的配置信息
	// 核心发现配置类的方法 loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader)
	// factoryType -> EnableAutoConfiguration.class
	// 发现factory.factories里面的这个org.springframework.boot.autoconfigure.EnableAutoConfiguration这个key的value的类
	// 自定义的starter也是利用了这个SPI的机制 网上自定义的starter的demo很多
	List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
			getBeanClassLoader());
	Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
			+ "are using a custom packaging, make sure that file is correct.");
	return configurations;
}

2. SpringgApplication

SpringgApplication构造器

public SpringApplication(Class<?>... primarySources) {
	this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	// servlet REACTIVE NONE webApplication属性
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	// spring.factories 初始化类
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	// spring.factories 监听类
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	this.mainApplicationClass = deduceMainApplicationClass();
}

SpringApplication.run

public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
	// java.awt.headless是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true,系统变量默认为true
	configureHeadlessProperty();
	// 从META-INF/spring.factories中获取监听器
	SpringApplicationRunListeners listeners = getRunListeners(args);
	listeners.starting();
	try {
		// 封装命令行参数
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		// 构造应用上下文环境,完成后回调SpringApplicationRunListeners的environmentPrepared方法
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
		// 处理需要忽略的Bean
		configureIgnoreBeanInfo(environment);
		// 打印banner
		Banner printedBanner = printBanner(environment);
		// 创建webApplication容器
		context = createApplicationContext();
		exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
				new Class[] { ConfigurableApplicationContext.class }, context);
		// 准备上下文环境,将environment保持到IOC容器中
        // 执行applyInitializers 回调ApplicationContextInitializer的initialize方法
        // 回调SpringApplicationRunListeners的contextPrepared方法
        // 回调SpringApplicationRunListeners的contextLoaded方法
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
		// 完成组件的扫描,创建,加载等
		refreshContext(context);
		// 从beanFactory获取所有的ApplicationRunner
		// CommandLinedRunner进行回调
		afterRefresh(context, applicationArguments);
		stopWatch.stop();
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
		}
		listeners.started(context);
		callRunners(context, applicationArguments);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, listeners);
		throw new IllegalStateException(ex);
	}

	try {
		listeners.running(context);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, null);
		throw new IllegalStateException(ex);
	}
	return context;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值