Spring Boot学习(3)
自动配置原理
一.依赖管理
- SpringBoot使用了父项目做为项目管理
XML
依赖管理
<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>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
- 开发只需要导入starter场景启动器(Starter就是一个包含了若干个坐标定义的pom管理文件, 即包含了若干个依赖的信息)
XML
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
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、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
修改默认版本号 是使用依赖覆盖
XML
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
也可以直接在pom.xml中重写依赖来覆盖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
之所以在配置了< parent>之后不需要填写版本号 是因为 < parent>中使用了< dependencyManagement>管理
注意:
- 当导入一个Starter时又想导入一些其他技术 又不想直接导入其他的Starter 可以直接导入该技术的依赖 而且只需要写GAV中的GA而不需要写V 但是如果< Parent>中没有该依赖时 就需要完整写上GAV
二🌓自动配置:
- 自动配好Tomcat
-
- 引入Tomcat依赖。
- 配置Tomcat
XML
<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 指定扫描路径(更改方式)
JAVA
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
- 各种配置拥有默认值
-
- 默认配置最终都是映射到某个类上,如:MultipartProperties
- 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
- 按需加载所有自动配置项
-
- 非常多的starter
- 引入了哪些场景这个场景的自动配置才会开启
-
- SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
- ….
容器中的注解的功能
一❓@Configuration(配置类):
使用:
- 用在类的上方 表示该类为配置类 可以与@Bean标签一起使用 作用类似于Spring.xml文件中< bean>创建对象
告诉springboot这个是一个配置类 == 配置文件
-
配置类里面使用@Bean标注在方法的上面给容器注册组件,默认也是单实例的
-
配置类本身也是组件
-
proxyBeanMethods()方法:代理bean的方法
-
当@Configuration中的参数proxyBeanMethods 的值为true时为代理模式 Cglib代理 会在原来的方法上增加功能 判断容器中是否已有对象 单例模式
-
当@Configuration中的参数proxyBeanMethods 的值为false时为非代理模式 就是非单例模式
-
Full模式(proxyBeanMethods = true)(保证每个@Bean方法被调用多少次返回的组件都是单实例的)
-
Lite模式(proxyBeanMethods = false)(每个@Bean方法被调用多少次返回的组件都是新创建的)
- 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
- 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
JAVA
@Configuration
public class MyConfig {
/**
* 外部无论对配置类中的这个组件注解方法调用多少次,获取的都是之前注册容器中的单实例对象
*
*
*
* //给容器中添加组件.以方法名作为组件的id,返回类型的,就是组件在容器中的实例
* @return Cat
*/
@Bean 方法名就是实例的名称
public Cat cat(){
return new Cat("彭芳姐");
}
}
测试发现 Full模式(proxyBea+nMethods = true) 使用的是Cglib代理模式
JAVA
com.dyw.application.config.MyConfig$$EnhancerBySpringCGLIB$$c5874a7@120d3fd
Lite(proxyBeanMethods = true)则是没有被代理
JAVA
com.dyw.application.config.MyConfig@29fa6b65
1. 1 @Import
@Import({Cat.class})
给容器中自动创建出这个类型的组件 默认组件的名字为全类名
JAVA
@Import({User.class})
@Configuration(proxyBeanMethods = false)
public class Config {
}
JAVA
boolean bean = context.containsBean("com.dyw.springboot.entity.User");
JAVA
true
1.2 @Conditional
- 条件装配: 满足Conditional指定的条件,则进行组件注入
- @ConditionalOnBean
- @ConditionalOnMissingBean
- @ConditionalOnMissingClass
- @ConditionalOnResource
- @ConditionalOnJava
- @ConditionalOnWebApplication
- @ConditionalOnNotWebApplication
- @ConditionalOnClass
使用在@Configuration注解类中的@Bean标签下 根据注解条件判断是否注入
JAVA
@Bean
@ConditionalOnBean(Cat.class)
public User user(){
User user = new User();
user.setCat(cat());
return user;
}
二: @SpringBootApplication(主程序类或引导类)
- 类上加上@SpringBootApplication 表示该类为主程序类
- 在类中写上主方法(main) 调用 SpringApplication.run(主程序类.class, args);即可开始SpringBoot程序
- 注意 组件都要写到主程序类的同级或是子级目录
- SpringApplication.run()方法会返回SpringBoot的容器 可以根据容器的getBean(“组件名”,类名.class)获取组件
- SpringApplication.run(主程序类.class, args)方法会返回一个Context上下文对象(容器), 里面包含了DispatcherServlet等对象, 这也是问什么运行此方法就可以达到实现web应用的功能. 通过内嵌的TomCat服务器核心就可以读取这个容器的组件.
- SpringBoot内嵌的服务器核心同样也是通过组件的方式存在SpringBoot的Context上下文对象中.(因为TomCat是java写的 运行原理就是执行java对象 所以把Tomcat的对象的创建和管理交给了SpringBoot);
三: @Bean
-
用于配置类的方法上 用来注册组件 使得组件管理的主权在容器
JAVA @Bean public Cat cat(){ return new Cat("彭芳姐"); }
方法名就是组件的名称 也可以在@Bean中设置组件的名称 @Bean(“组件名”)
-
创建组件的方法有两种
-
一种是利用有参构造创建组件 可以利用有参构造注入
JAVA @Bean public Cat cat(){ return new Cat("彭芳姐"); }
-
另一种是利用无参构造 需要后续使用set方法注入 或是利用spring中的注解注入
JAVA @Bean public Cat cat(){ return new Cat(); }
-
四: @RestController
- @RestController = @Controller + @ResponseBody
即**@RestController在@Controller的基础上 集成了@ResponseBody**的特性 即将java对象转换为json数据或是其他数据
- @ResponseBody 注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML 数据。
注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
- @ResponseBody是作用在方法上(可使用在类上表示整个类中的方法都受@ResponseBody的影响)的,@ResponseBody 表示该方法的返回结果直接写入 HTTP response body 中,一般在异步获取数据时使用【也就是AJAX】。
- 注意:在使用 @RequestMapping后,返回值通常解析为跳转路径,但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP response body 中。 比如异步获取 json 数据,加上 @ResponseBody 后,会直接返回 json 数据。@RequestBody 将 HTTP 请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。
五🦅@RequstMapping
在SpringMVC的学习中我们知道 被它标注的方法称为处理器方法 , 它可以标注一个处理器方法的请求路径, 被他修饰的处理器方法, 默认返回值通常解析为跳转路径
在SpringBoot中 它的功能被细分了
原本的**@RequestMapping**在不指定请求方法时,会接收任意请求方法的请求
但是SpringBoot中推荐不直接在方法而是使用功能更细的**@请求方法名Mapping** 例如**@GetMapping或是@PostMapping**
而把@RequstMapping用在类上 用来当访问路径的前缀
http://localhost:8088/dyw/cat
JAVA
@RestController
@RequestMapping("/dyw")
public class Controller {
@GetMapping("/cat")
public String doCat(){
return null;
}
}
六:@PathVariable(常用于REST风格)
- 绑定路径参数于处理器方法形参间的关系,要求路径参数名于形参名一一对应
- 使用: 用在SpringMVC控制器方法形参定义前面
- @PathVariable常用于RESTful中且 请求路径参数只有较少数量时 如一个
注意:参数是在路径上的使用{参数名称}描述路径参数
PLAINTEXT
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id){
System.out.println("user delete..."+id);
return "{'module':user delete}";
}
@RequestBody
- 用来接收Josn请求
json请求传参方式
JSON
{
"id":12
}
使用键值对的方式传参 **键名+”:”+值 ** 键值放在{}中
@RequestParam
- 用于接收url地址传来的参数 或是表单提交的参数 但路径传参的格式相对于RESTful的**@PathVariable**麻烦一点
HTTP
@RequestParam
http://localhost:0000/users?id=1
=====================================================
@PathVariable
http://localhost:0000/users/1
@RequestBody、@RequestParam和@PathVariable总结
- 应用
- 后期开发中,发送请求参数超过一个时 ,以json格式为主,@RequestBody应用较广
- 如果发送非json格式数据,选用@RequestParam接收参数
- 采用RESTful进行开发,当参数数量较少时,例如一个可以采用@PathVariable接收请求路径变量,通常用于传递id值
七:@ImportResource
-
该注解可以导入原生的配置文件 例如Spring中的Bean.xml配置文件 让其生效
-
使用在任意配置类上
JAVA @Import({Cat.class}) @ImportResource("classpath:Bean.xml") @Configuration(proxyBeanMethods = false) public class Config { }
Bean.xml
XML <?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="user" class="com.dyw.springboot.entity.User"> <property name="cat" ref="cat"/> </bean> <bean id="cat" class="com.dyw.springboot.entity.Cat"/> </beans>
八: @ConfigurationProperties
-
配置绑定 使用该注解 可以使用java读取到的配置文件(xml properties yml)中的内容,并且把它封装到JavaBean中,以供随时使用
PROPERTIES mycar.name=BYD mycar.price=10
-
方式一: 在JavaBean上加上@Component(将其注册到springboot容器)和@ConfigurationPropertes注解
JAVA @Data @Component @ConfigurationProperties(prefix = "mycar") public class Car { private String name; private Integer price; }
-
方式二:在JavaBean上只用加上@ConfigurationPropertes注解 并且在配置类(@Configuration)上加上@EnableConfigurationPropertes(Class<?>[])
JAVA @EnableConfigurationProperties(Car.class) //1. 开启Car配置绑定功能 //2. 把这个Car这个组件自动注册到容器中 @Configuration(proxyBeanMethods = false) public class Config { } @Data @ConfigurationProperties(prefix = "mycar") public class Car { private String name; private Integer price; }
-
方式二:在JavaBean上只用加上@ConfigurationPropertes注解 并且在配置类(@Configuration)上加上@EnableConfigurationPropertes(Class<?>[])
JAVA @EnableConfigurationProperties(Car.class) //1. 开启Car配置绑定功能 //2. 把这个Car这个组件自动注册到容器中 @Configuration(proxyBeanMethods = false) public class Config { } @Data @ConfigurationProperties(prefix = "mycar") public class Car { private String name; private Integer price; }