文章目录
一 SpringBoot特点
1.1 依赖管理
1.1.1 父项目做依赖管理
依赖管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
他的父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
1.1.2 开发导入starter场景启动器
- 1、见到很多
spring-boot-starter-*
: *就某种场景 - 2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
- 3、SpringBoot所有支持的场景
SpringBoot starters
4、见到的*-spring-boot-starter
: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖即为:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
1.1.3 无需关注版本号,自动版本仲裁
- 1、引入依赖默认都可以不写版本
- 2、引入非版本仲裁的jar,要写版本号。
1.1.4 可以修改默认版本号
1、查看spring-boot-dependencies
里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
1.2 自动配置
- 自动配好Tomcat
- 引入Tomcat依赖。
- 配置Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
- 自动配好SpringMVC
- 引入SpringMVC全套组件
- 自动配好SpringMVC常用组件(功能)
- 自动配好Web常见功能,如:字符编码问题
- SpringBoot帮我们配置好了所有web开发的常见场景
- 默认的包结构
- 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
- 无需以前的包扫描配置
- 想要改变扫描路径:
@SpringBootApplication(scanBasePackages="com.atguigu")
■ 或者@ComponentScan 指定扫描路径
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
● 各种配置拥有默认值
- 默认配置最终都是映射到某个类上,如:
MultipartProperties
- 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
● 按需加载所有自动配置项 - 非常多的starter
- 引入了哪些场景这个场景的自动配置才会开启
SpringBoot
所有的自动配置功能都在spring-boot-autoconfigure
包里面
● …
二 容器功能
2.1 组件添加
2.1.1 @Configuration
Full
模式与Lite
模式
■ 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
■ 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
一定要注意: proxyBeanMethods 属性是用来判断@Bean 标记的方法会不会被代理的,i.e.,@Bean的方法(注意是方法) 会不会返回单例
// Configuration使用示例
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*/
@SpringBootApplication
@RestController
public class TestRunner {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TestRunner.class);
Assert.isAssignable(ApplicationContext.class, context.getClass());
MyConfig config = context.getBean(MyConfig.class);
User user1 = config.user();
User user2 = config.user();
Assert.isTrue(user1 == user2, "");
}
}
/** 一定要注意: 这个 proxyBeanMethods 并不是说 每个@Bean都返回单例或非单例;
* 而是说,多次调用 MyConfig @Bean标记的方法会不会返回单例或非单例对象*/
@Configuration(proxyBeanMethods = true)
class MyConfig {
@Bean()
public User user() {
return new User("ht", 19);
}
}
2.1.2 @Bean、@Component、@Controller、@Service、@Repository
2.1.3 @ComponentScan、@Import
@Import
: Indicates one or more component classes to import — typically@Configuration
classes.
//...
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
//....
}
2.1.4 @Conditional
@Conditional
有很多的派生注解:
简单的demo:
@SpringBootApplication
public class TestConditionalAnnoRunner {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TestConditionalAnnoRunner.class);
User bean = context.getBean(User.class);
Assert.notNull(bean, "not null a user");
System.out.println(bean);
}
}
@Configuration
class Config {
@Bean
@ConditionalOnClass(Book.class)
public User user() {
return new User("ht2", 10);
}
}
2.2 原生配置文件引入
2.2.1 @ImportResource
这个注解主要是为了 兼容旧代码的xml配置 或者 第三方包中的xml 文件
@SpringBootApplication
@ImportResource(value = "beans.xml")//默认就会找到类路径下
public class TestImportResourceRunner {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TestImportResourceRunner.class);
User bean = context.getBean(User.class);
Assert.notNull(bean, "not null");
System.out.println(bean);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="haha" class="com.xkcoding.helloworld.User">
<property name="userName" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
</beans>
2.2.2 配置绑定 (@ConfigurationProperties
)
场景: 使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用.一种做法是使用 Properties
手动读. 另一种,可以使用@ConfigurationProperties
2.2.3 @EnableConfigurationProperties + @ConfigurationProperties
2.2.4 @Component + @ConfigurationProperties
@SpringBootApplication
@EnableConfigurationProperties(Car.class)
public class TestConfigurationPropertiesRunner {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TestConfigurationPropertiesRunner.class);
Car car = context.getBean(Car.class);
System.out.println(car);
}
}
// 注意: 配置文件的名字一定要叫做 application.properties
// 这里的 prefix 其实是起到了 命名区间的作用,也可以视为 业务命名
//@Component (假如 @EnableConfigurationProperties(Car.class)已经指定了,则这里不需要显式将加入Spring容器 )
@ConfigurationProperties(prefix = "good")
class Car {
private String brand;
//geter ,setter ,toString
}
// !!! 如果不是读application.yaml 或 application.properties中的配置,需使用
// @PropertySource() 指定配置文件
2.3 自动配置原理入门
2.3.1 引导加载自动配置类
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{}
2.3.2 @SpringBootConfiguration
@Configuration
。代表当前是一个配置类
2.3.3 @ComponentScan
指定扫描哪些,Spring注解;
2.3.4 @EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
2.3.4.1 @AutoConfigurationPackage
自动配置包?指定了默认的包规则
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
2.3.4.2 @Import(AutoConfigurationImportSelector.class)
- 1、利用
getAutoConfigurationEntry(annotationMetadata)
;给容器中批量导入一些组件 - 2、调用
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)
获取到所有需要导入到容器中的配置类 - 3、利用工厂加载
Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader)
;得到所有的组件 - 4、从
META-INF/spring.factories
位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories
位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar
包里面也有META-INF/spring.factories
文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
2.3.4.3 按需开启自动配置项
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional
),最终会按需配置。
2.3.5 修改默认配置
典型的一个例子,给容器中加入了文件上传解析器;
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先,再比如:
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
}
2.3.6 总结
SpringBoot
先加载所有的自动配置类xxxxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。
xxxProperties
里面拿。xxxProperties
和配置文件进行了绑定 - 生效的配置类就会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能就有了
- 定制化配置
- 用户直接自己
@Bean
替换底层的组件 - 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties
- 用户直接自己
2.4 最佳实践(使用Springboot的一般思路)
- 引入场景依赖
spring.io 链接 - 查看自动配置了哪些
- 自己分析,引入场景对应的自动配置一般都生效了
- 或者: 配置文件中
debug=true
开启自动配置报告。Negative(不生效)\Positive(生效)
- 是否需要修改
- 参照文档修改配置项
配置项修改 - 自己分析。
xxxxProperties
绑定了配置文件的哪些。 - 自定义加入或者替换组件
@Bean、@Component
- 自定义器
XXXXXCustomizer
- 参照文档修改配置项
2.5 spring intializer
IDE 提供了方便创建springboot 项目的入口: