依赖管理
- 父项目做依赖管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
父项目的父项目 --> 打开父项目的jar包,发现他还继承下面父类
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
这个父类中几乎声明了所有开发中常用的jar的版本号,所以在导入jar的时候不需要写版本号(自动版本仲裁机制)
自动仲裁:每个版本的springboot已经把所有对应的jar包的版本号都规定好了
- 开发导入starter场景启动器
2、只要引入starter,这个场景的所有常规需要的jar依赖我们都自动引入
3、SpringBoot所有支持的场景(可以在官网查看)
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖都会依赖一个 spring-boot-starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
- 无需关注版本号,自动版本仲裁
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。(如果引入的jar包springboot没有,就必须自己写版本号)
- 可以修改默认版本号,使用其他版本的jar
(通过maven的就近优先原则,更改版本号)
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面 pom.xml文件的 properties 标签内部写对应jar包的版本号:
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
1.2、自动配置
- 自动配好Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
- 自动配好SpringMVC
- 自动配好Web常见功能,如:解决字符编码问题
- SpringBoot帮我们配置好了所有web开发的常见场景
默认的包结构主程序(带有@SpringBootApplication)所在包及其下面的所有子包里面的组件都会被默认扫描进来主程序运行,会默认扫描本包 及其 下子包
- 无需以前的包扫描配置
- 想要改变扫描路径方法:
方法一:主程序的 @SpringBootApplication(scanBasePackages="扫描的包")方法二: @ComponentScan(“扫描路径”)
注解 等同于 、、 ("com.atguigu.boot")三个注解
- 各种配置拥有默认值
- 默认配置最终都是映射到某个类上,如:文件上传的最大为1MB会映射到MultipartProperties类上
- 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
- 按需加载所有自动配置项
- 非常多的starter
- 引入了哪些场景这个场景的自动配置才会开启
- SpringBoot所有的
自动配置功能都在 spring-boot-autoconfigure 包里面
- ......
容器功能
组件的添加
在spring中都是创建一个beans.xml在里面添加组件(bean对象)
1、@Configuration注解
- 作用:声明一个类为配置类(等同于我们以前的配置文件)
- 注意:
配置类本身也是组件
- (会作为一个对象放到IOC容器中)
- springboot2中多了一个
proxyBeanMethods
- 属性
- proxyBeanMethods属性的默认值是true
- proxyBeanMethods:代理bean的方法
- 如果
proxyBeanMethods = true
- ,Full模式,调用IOC中配置类的方法,多次调用的得到的对象
是同一个(单例的)
- 为true,为
代理对象调用方法
- 。SpringBoot总会检查这个组件是否在IOC容器中有。有的话直接拿,没有创建,保持组件单实例
- 如果proxyBeanMethods = false,Lite模式调用IOC中配置类的方法,多次调用的得到的对象
不是同一个(多例的)
- 为false,每个@Bean方法被调用多少次返回的组件都是新创建的
- Full模式与Lite模式可以解决组件间的依赖问题
- 示例:
- 配置 类组件之间
无依赖
-
- 关系用
Lite多例模式
-
- 加速容器启动过程,减少判断,快
- 配置类组件之间
有依赖
-
- 关系,
Full单例模式
-
- ,方法会被调用得到之前单实例组件,慢
#############################Configuration使用示例######################################################
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
*/
(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
//给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
################################测试代码如下########################################
("com.atguigu.boot")
public class MainApplication {
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
//3、从容器中获取组件,如果两个相等,就说明为单实例的
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("组件:"+(tom01 == tom02));
//4、其实配置类本身也相当于一个组件
//com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
//如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。有直接拿(单例)
//如果 proxyBeanMethods = false,调用IOC中配置类的方法,多次调用的得到的对象 不是同一个(多例的)
User user = bean.user01();
User user1 = bean.user01();
System.out.println(user == user1);
//@Configuration(proxyBeanMethods = true) 用户的宠物是容器中的宠物
//@Configuration(proxyBeanMethods = false) 用户的宠物是不是容器中的宠物
User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);
System.out.println("用户的宠物:"+(user01.getPet() == tom));
}
}
2、常见组件添加的注解
1、@Bean 注解
- 使用位置: 方法上
- 作用:给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
- 属性:
- 无属性的时候,默认方法名作为组件的id,可以使用id属性设置组件的id
- 当只有这一个属性的时候,可以省略
- 注意:配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
2、@Component、@Controller、@Service、@Repository 注解
- 使用位置:类上
- 作用:
- 在学spring的注解方式创建bean对象组件,在这里同样适用
3、@ComponentScan
- 使用位置:类上
- 作用:包扫描
- 在学spring的注解方式,进行包扫描一样使用
- 有value属性、basePackages属性: 都可以指定要扫描的包
4、@Import
- 使用位置:类上(配置类、组件类)
- 作用:给容器中导入多个组件
- 给容器中自动创建出这的组件
- 默认组件的名字就是全类名
//@Import({User.class, DBHelper.class})
// 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
({User.class, DBHelper.class})
(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}
5、@Conditional
- 作用:条件装配,满足Conditional指定的条件,则进行组件注入
- 位置:类上(配置类上),方法上
- 放在方法上,如果符合响应的要求,创建对应方法返回值的组件
- 放到类(配置类)上,当符合要求的时候,创建配置类所有的组件,否则不创建配置类下的组件
- 属性:
- name : 指定组件的名称(判断容器中是否有该名称的组件)
- value : 指定组件的类型Class(判断容器中是否有该类型的组件)
- 注意:
- @Conditional注解是一个根注解,他有许多的派生注解
- 派生注解:
- @ConditionalOnBean注解:当容器中存在指定的组件的时候,才会做某些事情
- @ConditionalOnMissingBean注解:当容器中不存在指定的组件的时候,才会做某些事情
- @ConditionalOnClass注解:当容器中有某一个类的时候,才会做某些事情
- @ConditionalOnMissingClass注解:当容器中,没有某一个类的时候,才会做某些事情
- @ConditionalOnResource注解:当容器中项目的类路径里面存在某些资源的时候,才会做某些事情
- @ConditionalOnJava注解:是指定的java版本号的时候,才会做某些事情
- @ConditionalOnWebApplication注解:当我们的应用是一个web应用的时候,才会做某些事情
- @ConditionalOnNotWebApplication注解:当我们的应用不是一个web应用的时候,才会做某些事情
- @ConditionalOnProperty注解:当配置文件配置了指定的属性的时候,才会做某些事情
- @ConditionalOnSingleCandidate注解:指定的组件有一个实例或者有多个实例一个主实例的时候,才会做某些事情
- .....