一.什么是 SpringBoot?
1.在没有 SpringBoot 之前我们的架包都需要找以及可能会发生架包冲突问题,而且整合项目也是比较复杂,有了 SpringBoot 可以很好的解决架包问题以及可以快速的整合第三方框架让开发者可以更专注于业务代码上当然 SpringBoot 的强大不止于此如一些核心的功能等.....
二.SpringBoot 核心功能
1.独立运行Spring项目
SpringBoot 中我们可以通过对文件进行打包以 jar 包的形式进行独立运行
<build>
<plugins>
<!-- Springboot打包的插件-->
<!-- 打包完后 target 会有对应的 jar 包 然后在文件中进行 java -jar jar 包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.内嵌servlet容器
SpringBoot中默认使用Tomcat作为嵌入式的Servlet容器,还可以以选择内嵌Jetty或者Undertow,无须以war包形式部署项目。
运行的时候我们可以注意到 SpringBoot 默认使用了 Tomcat 当做我们的Web 服务器
3.简化的Maven配置:Spring提供推荐的基础 POM 文件来简化Maven 配置
当我们使用 SpringBoot 后我们会发现第一个很好的体验就是 不需要再去手动导入 jar 包以及去耗费大量的事件去找 jar 包和开发时遇到团队 jar 包依赖冲突问题
4.自动配置Spring:Spring Boot会根据项目依赖来自动配置Spring框架,极大地减少项目要使用的配置
5. 无代码生成和XML配置:在 SpringBoot 中我们的依赖架包已经由我们的 Maven 进行统一化管理了这一切都是借助于条件注解完成的。
三.SpringBoot 自动装配
1.为什么要使用自动装配?
由于SpringBoot无法预知所有需要装配的bean,因此就需要一种机制查找需要装配的 bean
2.SpringBoot 自动装配原理:
Spring Boot的自动装配实际上是从META-INF/spring.factories文件中获取到对应的需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给Spring容器进行管理。
简单理解就是通过注解和一些简单的配置就能将某些组件载入Spring容器环境中,便于使用。
在SpringBoot 在启动类中 main()方法上有一个@SpringBootApplication注解,@SpringBootApplication注解也被称为组合注解,从字面意思上我们可以理解为有很多注解进行组合而形成的注解当我们运行的时候那些被组合的注解也起到了很多作用,我们可以点进去看一下
其中@SpringBootConfiguration和@EnableAutoConfiguration还有@ComponentScan( excludeFilters...是比较重要的
1.@SpringBootConfiguration:点击进去我看可以查看@SpringBootConfiguration实质就是@Configuration这个注解实际上就是代表了一个配置类,相当于一个beans.xml文件,使用方法如下:
//表示当前类是一个配置类/配置文件
@Configuration
public class DataSourceConfig {
//@Bean 代表给容器注入一个bean
//如<bean id="TestDataSource" class="DataSource" value="xxxx"></bean>
//@Bean("data") 也可以自定义方法名否则为默认该方法的方法名
@Bean
public DataSource TestDataSource(){
return new DataSource(1001,"192.3221");
}
}
2.@EnableAutoConfiguration:我们通过翻译可以知道该注解是开启SpringBoot自动装配的意思,我们点击进去查看源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
源码中@AutoConfigurationPackage(将添加该注解的类所在的package作为自动配置package进行管理)自动配包,@Import(AutoConfigurationImportSelector.class)这是Spring底层注解,表示给容器导入什么组件,借助@Import({AutoConfigurationImportSelector}),@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器里,我们可以继续往AutoConfigurationImportSelector里面看:
从中我们可以看到AutoConfigurationImportSelector类实现了DeferredImportSelector接口而DeferredImportSelector接口继承了ImportSelector类在ImportSelector类中只有一个方法selectImports()那这样我们就可以顺理的理解为AutoConfigurationImportSelector类中的selectImports()方法是核心我们现在从selectImports()方法开始看
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//判断是否开启自动配置
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
}
我们可以看到到最后我们会将我们的方法通过判断然后进行调用getCandidateConfigurations()
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}
这个方法本身没有什么,但是调用了一个loadFactoryNames方法,我们跟进去看看。发现在SpringFactoriesLoader类里存在一个静态方法。
public static List<String> loadFactoryNames(
Class<?> factoryType,
@Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
该方法调用本类的一个静态方法loadSpringFacories方法,获得一个List集合,继续跟进去。
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) { Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
Enumeration urls = classLoader.getResources("META-INF/spring.factories"); while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator();
// ........ 省略代码
}
}
// ........ 省略代码
return result;
} catch (IOException var14) {
throw new IllegalArgumentException(
"Unable to load factories from location [META-INF/spring.factories]", var14);
}
}
}
我们发现一个核心配置文件,**META-INF/spring.factories**,找下这个文件
Spring Boot的自动装配实际上是从META-INF/spring.factories文件中获取到对应的需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给Spring容器进行管理
3.@ComponentScan:我们翻译可以知道这个注解是组件扫描的意思是扫描注解,再看一下我们经常用的@Controller,@Service,@Repository注解查看其源码你会发现,他们中有一个共同的注解@Component,SpringBoot会把指定路径下带有指定注解的类自动装配到bean容器里。会被自动装配的注解
四.总结
使用Spring Boot可以做到专注于Spring应用的开发,而无需过多关注XML的配置。Spring Boot使用“习惯优于配置”的理念,简单来说,它提供了一堆依赖打包,并已经按照使用习惯解决了依赖问题。使用Spring Boot可以不用或者只需要很少的Spring配置就可以让企业项目快速运行起来。
如有不对的地方请各位大佬及时指出!!谢谢!!!