SpringBoot学习记录(三)

自动配置原理入门

针对已经学习到的SpringBoot帮我们完成的各种任务,今天来简单看一看它是如何帮助我们实现自动配置流程的。

首先还是从启动类出发,这里我们发现这个入口上只有一个注解@SpringBootApplication,这个注解标记了我们项目的启动类,当我们点击进入这个注解后可以看到:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

除去一些元注解,这里列出了一些这个注解需要实现的功能注解,首先是我们前面所了解过的@ComponentScan包扫描,这个我们很熟悉了就不再多说。

然后是@SpringBootConfiguration,这个注解看名字其实就是SpringBoot的配置注解,当我们点入就可以看到是几个元注解和我们之前学到的@Configuration配置注解,也就是证明这个类是一个配置类:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed

这个@Indexed其实就是在类逐渐增多的情况下,为了加快启动的解析速度所设置的,项目启动会优先从索引开始,而不是全局的包扫描。

最后就是这个@EnableAutoConfiguration注解,字面翻译的话大概就是确保自动配置,当我点入这个注解后会发现:

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}

它是除了其他元注解外剩余的注解,类中的其他代码我暂时删掉了,这里面@Import我们之前已经了解过,同时我们点开@AutoConfigurationPackage也可以发现它其实也包含了一个@Import,不同的是导入的类是AutoConfigurationPackages.Registrar.class

这里我们先看AutoConfigurationImportSelector.class这个类的实现,这个类中方法非常多,我们先看这一个就可以:

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

首先我们可以很清楚的看到,它首先获取到的配置的元数据,通过元数据又设置了一个方法getAttributes获取其中的注解参数,获取到注解参数后,调用了getCandidateConfigurations方法,这个方法我们点击可以发现,他是实现了一个把元数据中不同的参数存入了一个ArrayList列表,并且校验了集合产生是否为空,如果为空会输出日志参数。这里它的loadFactoryNames方法将从META-INF/spring.factories位置来加载一个文件,所有的配置都会被写死在这个文件下,每个导入的Spring模块都有这个路径文件。之后它对这个列表进行了去重,并又放入了LinkedHashSet中,进一步去重。之后又读取了参数中所存在的Conditional判断是否存在需要去除的类,如果存在,将会从建立好的集合中将其去除,最后返回一个内部类格式AutoConfigurationEntry。这个内部类中的所有参数都将被加入到容器中,作为后续调用的组件。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = new ArrayList<>(
				SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
		ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
		ClassLoader classLoaderToUse = classLoader;
		if (classLoaderToUse == null) {
			classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
		}
		String factoryTypeName = factoryType.getName();
		return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
	}

接下来是这个AutoConfigurationPackages.Registrar.class,这个里面其实就相对来说简单一些,主要是负责包的扫描和导入,基本方法和上述差不多,也是读取到注解信息后,通过new一个final的私有静态类:

PackageImports(AnnotationMetadata metadata) {
			AnnotationAttributes attributes = AnnotationAttributes
					.fromMap(metadata.getAnnotationAttributes(AutoConfigurationPackage.class.getName(), false));
			List<String> packageNames = new ArrayList<>(Arrays.asList(attributes.getStringArray("basePackages")));
			for (Class<?> basePackageClass : attributes.getClassArray("basePackageClasses")) {
				packageNames.add(basePackageClass.getPackage().getName());
			}
			if (packageNames.isEmpty()) {
				packageNames.add(ClassUtils.getPackageName(metadata.getClassName()));
			}
			this.packageNames = Collections.unmodifiableList(packageNames);
		}

同样的转为一个集合交给容器管理。

此时我们就可以发现,其实SpringBoot在开始的时候会把所有的写好的配置信息,全部加载进来,每个配置信息都会根据条件选择是否再进行注入生效,默认的所有配置类都有它默认的配置信息,如果有自定义的用户配置,会优先使用用户的配置,覆盖掉默认信息。

配置信息到这里就差不多了,更多详细想要的信息可以从官方文档中根据自己的喜好进行查阅。

开发小工具

在众多的开发工具中我感觉这个Spring Initailizr(项目初始化向导)应该是对于新手来说最为实用的了,我们可以直接选择我们所需要的场景。
在这里插入图片描述
这里我们点击Next:

在这里插入图片描述
这里可以自定义自己的包名和Java版本,点击Next:
在这里插入图片描述
可以看到基本数所有的配置都可以进行勾选,包括SpringBoot的版本号也可以选择,包括一些小插件,在Template Engines中可以自己选择,再点击Next后选择创建的文件目录后就可以打开项目了,创建好项目后,他会帮助我们生成固定的文件格式:
在这里插入图片描述当然这里的Config和Pojo是我自己创建的,大家创建的时候是没有的,其他的目录格式都是系统帮助我们完成的,而且我们学习的配置信息,也根据我们需要的场景都写入了Pom文件,我们无需再关心,非常的方便快捷。

这里的application.yml是我单独创建的配置文件,yml和properties都是很不错的配置文件,大家哪个熟悉就可以使用哪一个。

Lombok

关于Lombok这个插件大家可能也有听过,但是我还是不是很推荐大家使用,因为缺少了get\set函数的配置,会使得我们在调试的过程中出现问题,追溯路径过程可能会有点麻烦,不太适合新手上来的学习,而且她默认的生成所有属性的方法,可能会导致某些我们不想让外部访问的数据泄露,所以大家还是尽量使用自己写的JavaBean开发吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值