Spring底层
- 配置优先级
- Bean管理
- 获取bean
- Bean的作用域
- 第三方Bean
- SpringBoot原理
- 起步依赖
- 自动配置
- 自动配置的原理
- 自定义starter
配置优先级
Spring中的配置文件如果配置了相同的内容则根据配置优先级进行配置:
application.properties>application.yml>application.yaml
注意:虽然SpringBoot支持多种配置文件,但在项目开发时,统一使用一种格式的配置文件yml
SpringBoot 除了支持配置文件属性配置,还支持java属性配置和命令行参数的方式进行属性配置
java属性配置:-Dserver.port=9000
命令行参数:–server.port=10010
在项目打包之后如何配置命令行参数:
注意:SpringBoot项目打包时,需要引入插件,spring-boot-maven-plugin(基于官网骨架创建项目,会自动添加该插件)
java属性配置的优先级高于命令行高于三种配置文件
Bean管理
获取bean
默认情况下,spring项目启动时,会把bean都创建好存放在IOC容器中,主动获取bean对象:
根据name获取bean:
Object getBean(String name)
根据类型获取Bean
<T> T getBean(Class<T> requiredType)
根据name获取Bean(带类型转化):
<T> T getBean(String name,Class<T> requiredType)
@Autowiredprivate ApplicationContext applicationContext; //这是一个IOC容器对象public void caozuoBean(){// 根据名称得到bean对象DeptController bean1 = (DeptController) applicationContext.getBean("deptcontroller");//根据bean类型获取DeptController bean = applicationContext.getBean(DeptController.class);//根据bean的名称及类型获取DeptController bean2 = applicationContext.getBean("deptcontroller", DeptController.class);
输出这三个对象你会发现,输出的对象都是相同的对象,说明IOC容器中的Bean是单例的
Bean的作用域
可以通过 @Scope 注解来进行配置作用域:
@Scope("prototype")
@Restcontroller
@RequestMapping("/depts/")
public class Deptcontroller(){
}
注意:默认singleton的bean,在容器启动的时候被创建,可以使用 @Lazy注解来延迟初始化(延迟到第一次使用时)。
prototype的bean,每一次使用该bean的时候都会创建一个实例
实际开发过程中,绝大部分的Bean都是单例的,也就是说绝大部分Bean不需要配配置scope属性
第三方Bean
如果要管理的bean对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明的bean的,就需要用到 @Bean注解
若要管理的第三方bean对象,建议对这些类进行集中配置,可以通过 @Configuration注解声明一个配置类,这个注解的底层也是 @Component
通过 @Bean注解的name/value的属性指定bean名称,如果未指定,则默认为方法名
如果第三方bean需要依赖其他bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配
在类中:
@Bean //将方法的返回值交给IOC容器来管理,成为IOC容器的bean对象
public SAXReader saxreader(){
return new SAXReader();
}
这种方法一般不建议,建议在配置类中进行声明:
@Configuration
public class CommonConfig{
@Bean
public SAXReader saxreader(){
return new SAXReader();
}
}
但是在Spirng导入类中未必会将所有的Bean都加载到IOC容器中,可能会出现扫描不到的问题
SpringBoot原理
起步依赖
Spring中的最基础框架,Spring FrameWork框架,但是使用它直接进行项目的开发会十分的繁琐,项目的依赖配置等都必须手动亲自完成,包括依赖的版本都必须亲自进行匹配(不然会出现版本冲突问题) ,SpringBoot框架可以简化Spring FrameWork的开发(通过起步依赖,自动配置两大功能来简化Spirng的配置好问题)
- 起步依赖
起步依赖也是通过maven的依赖传递进行相关依赖的配置
自动配置
SpringBoot的自动配置就是当Spring容器自动启动后,一些配置类,Bean对象就自动的存入到IOC容器当中,不需要我们去手动声明,从而简化了开发,省去了繁琐的步骤
Gson 的gson对象,是处理json数据的工具对象,他可以生成json的字符串,我们在类中可以直接调用该类,是因为在创建初期Spring就已经将这个类配置好了
@Autowired
private Gson gson;
public void TestJson(){
String json=gson.tojson(Result.success());
System.out.println(json);
}
自动配置的原理
就是如何解释,项目中引入依赖之后,如何将依赖直接加载到项目的Spring IOC容器之中的
这个时候我们就要引进一个问题:
如果这个时候我们引进了一个自定义的第三方依赖包,在项目中引进这个第三方依赖包,但是当我们注解注入后运行时发现找不到这个第三方依赖包为什么?
因为当我们引进第三方依赖包的时候,在主方法类中的注解 @SpringBootApplication 对bean进行扫描,但是范围仅限于其所在包及其子包,第三方依赖不在其范围不能被他扫描到
针对这个问题:
方案一:我们可以通过 @ComponentScan注解组件扫描
同时也可以将项目中扫描不到的Bean重新进行扫描
@CompomentScan({包名})
@springBootApplication
public class SpringbootWebConfig2Application{
}
由于方案一非常繁琐(没要导入新的包,都需添加新的扫描)
方案二:通过 @import导入,使用注解导入类会被Spring加载到IOC容器当中去,导入的注解主要有:普通类,配置类,ImportSelector接口实现类
通过 @import注解进行导入 (普通类以及配置类):
@import({TokenParser.calss,HeaderConfig.class})
@SpringBootApplication
public class SpringBootWebConfigApplication{
}
导入ImportSelector接口实现类:
当进行接口实现类时:
@Import({MyImportSelector.class})
@springBootApplication
public class SpringBootWebConfigApplication{
}
在接口实现类中重写方法,返回字符串类型数组,这里将我们要加载到bean对象的全类名放到数组中,在通过 @import注解将数组中的类都加载到IOC容器之中
除此之外,第三方也可以自己给出自定义的第三方注解 @EnableXxx自定义注解中就实现了 @import
同时也可以通过自定义注解@Import注解放在其中,之后直接通过自定义注解完成该功能,@EnableXxx
@EnableHeaderConfig
@springBootApplication
public class SpringBootWebConfigApplication{
}
- 剖析SpringBoot自动配置的原理
我们从SpringBoot的引导类的注解 @SpringBootApplication开始进行剖析
其中 @EnableAutoConfiguration注解中, @Import注解中将配置类文件中所有的配置类返回到数组中将他们都注入到IOC容器之中
@Conditional
作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring IOC容器中
位置:方法,类
Conditional
本身是一个父注解,派生出大量的子注解:
@ConditionalOnClass
:判断环境中是否有对应字节码文件,才注册bean到IOC容器
@ConditionalOnMissingBean
:判断环境中没有对应的Bean(类型或名称),才注册bean到IOC容器当中
@ConditionalOnproperty
:判断配置文件中对应属性和值,才注册bean到IOC容器
@ConditionalOnClass(name="io.jsonwebtoken.Jwts")
@ConditionalOnMissingBean
@ConditionalOnproperty(name="name",havingValue="")
例如:
@Bean
@ConditionalOnMissingBean
public Gson gson(...){
}
自定义starter
在实际开发中,经常会定义一些公共组件,提供各个项目团队使用。而在SpringBoot的项目中,一般会将这些公共组件封装为SpringBoot的starter
如何区分官方的组件和其他的组件:
官方的组件命名时 spring-boot-starter-web 这样的,而其它的项目组件的功能名称在前,例如:mybatis-spring-boot-starter
需求:自定义aliyun-oss-spring-boot-starter,完成阿里云OSS操作工具类AliyunOSSUtils的自动配置
目标:引入起步依赖之后,要想使用阿里云OSS,注入AliyunOSSUtils直接使用即可
步骤: