当前位置:网站首页>二、自动配置之底层注解
二、自动配置之底层注解
2022-08-05 05:16:00 【呆比特】
自动配置之底层注解
为了更好的学习SpringBoot的自动配置原理,我们先来了解一下底层用到的几个注解!
0. 项目准备
首先我们来准备两个实体类Pet 和 User,如下:
如果按照以前配置文件的方式,我们需要在resources下创建beans.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="user01" class="com.dbt.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="cat" class="com.dbt.boot.bean.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>
但是,我们现在不想使用配置文件的方式了,还能怎么办呢?接下来就到我们的注解登场了!
1. @Configuration
我们可以创建一个类MyConfig,给类上边添加@Configuration注解,就表示这是一个配置类,这个配置类就相当于以前的配置文件,只不过改变了一种表现形式而已,如下:
@Configuration
public class MyConfig {
public User user01(){
return new User("zhangsan", 18);
}
@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
在配置类里面,我们可以使用@Bean注解标注在方法上,给容器注册组件,这里默认以方法名作为组件的id,但是如果我们在注解中自己指定了名称,就以我们自己指定的为准;返回类型就是组件类型;返回的值,就是组件在容器中的实例,其默认也是单实例的,而且,我们的配置类本身也是一个组件。
我们可以验证一下
public class MainApplication {
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("----组件tom01 == tom02吗----:"+(tom01 == tom02));
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
}
}
仔细的朋友可能会问了,那个绿色的那一串是什么呀,好像不是一个普通的对象?
是的,这就是与springboot1的不同了,springboot2的@Configuration注解有一个属性proxyBeanMethods,表示是否为一个代理bean的方法,默认为true。在true情况下,上边 MyConfig bean = run.getBean(MyConfig.class); 这句代码获取的本身就是一个代理对象,代理对象调用方法时,SpringBoot总会检查这个组件是否在容器中有,如果有就直接调用,保证对象的单例性。
如果将proxyBeanMethods属性改为false,获取到的就不是代理对象了,而且连续多次获取的对象用==比较会返回false,有兴趣的快去试试吧!
总结
■ @Configuration标注的类为配置类,里边使用@Bean注解注册组件,可以自己配置组件名称,否则默认为方法名.
■ @Configuration有一个属性proxyBeanMethods,默认true.
■ true(Full模式),保证每个@Bean方法被调用多少次返回的组件都是单实例的.
■ false(Lite模式),每个@Bean方法被调用多少次返回的组件都是新创建的.
■ 所以在组件依赖的场景下,必须使用true,来保证操作的是同一个对象.
○ 最佳实战
■ 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
■ 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
2. @Import导入
■ 向我们以前使用的
@Component:表示一个组件、
@Controller表示一个控制器、
@Service:表示一个业务逻辑组件、
@Repository表示数据库层组件、
@ComponentScan:指定包扫描路径
这些组件用法不变,这几就不在赘述了......
@Import标注在组件上,它是一个class的数组,我们可以利用它给容器中导入许多的组件,这些组件可以是我们自己的,也可以是第三方jar包里边的。将我们需要导入的组件标注在Import属性数组中,他就会帮我们调用那些组件的无参构造方法,给容器创建组件。
3. @Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
它是一个根注解,底下还有好多的派生注解,每个都代表不同的功能。我们以**@ConditionalOnBean**为例来看看:
@Configuration
public class MyConfig {
@Bean
public User user01(){
User zhangsan = new User("zhangsan", 18);
return zhangsan;
}
//@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
比如现在有这样一个配置类,现在我们给容器中注入了user01,而没有注入tom,可以验证一下:
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
boolean tom = run.containsBean("tom");
System.out.println("容器中有Tom组件吗:"+tom);
boolean user01 = run.containsBean("user01");
System.out.println("容器中有user01组件吗:"+user01);
}
}
现在我们给user01上边加上@ConditionalOnBean注解,表示如果没有tom组件,那我们也不要user01了.
@ConditionalOnBean(name = "tom")
@Bean
public User user01(){
User zhangsan = new User("zhangsan", 18);
return zhangsan;
}
诺,就这么简单,只有有tom组件,user01才能被注入。甚至它还可以标注在类上,当容器中有tom组件时,这个类中的一堆组件才能被注入,否则全都不注入。
像这样的派生注解还有那么多,快去试试吧!
4. @ImportResource导入Spring配置文件
这个就比较简单了,当我们项目中已经有beans.xml文件时,而现在想用配置类的方式,但是又不想将配置文件的组件一个一个转移成注解方式,就可以使用这个注解。
使用方法:在配置类上添加 @ImportResource(“classpath:beans.xml”),导入Spring的配置文件
5. @ConfigurationProperties配置绑定
通常,我们习惯于将经常变化的东西配到配置文件中,比如数据库连接信息等,然后从配饰文件解析到Java bean中。配置绑定就是用来实现这种场景的。
举个栗子
@ToString
@Data
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
}
现在有一个Car实例,里边有品牌和价格两个属性,我们现在利用配置绑定的方式,给这两个属性赋值。
@ConfigurationProperties(prefix = “mycar”) 这个注解表示,我们类里边的每个属性,和配置文件中哪个前缀下的所有属性一 一绑定。记得要加上@Component,因为只有容器中的组件才能拥有SpringBoot的这些功能。
application.properties
测试
这样就读到了配置文件的信息了,以后要修改只需要修改配置文件即可。
还有一种方式可以实现这样的功能,就是**@EnableConfigurationProperties(Car.class)这个注解,这个注解必须要标注在配置类上,它的作用是开启Car配置绑定功能,然后把Car这个组件自动注册到容器中**。
自动配置的底层注解就复习到这里啦,下篇再见!
边栏推荐
猜你喜欢
CVPR 2022 |节省70%的显存,训练速度提高2倍
MSRA proposes extreme masking model ExtreMA for learning instances and distributed visual representations
Kubernetes常备技能
Day1:用原生JS把你的设备变成一台架子鼓!
伪RTOS-ProroThread在CH573芯片上的移植
华科提出首个用于伪装实例分割的一阶段框架OSFormer
BFC详解(Block Formmating Context)
【论文阅读-表情捕捉】ExpNet: Landmark-Free, Deep, 3D Facial Expressions
[Pytorch study notes] 11. Take a subset of the Dataset and shuffle the order of the Dataset (using Subset, random_split)
IJCAI 2022|边界引导的伪装目标检测模型BGNet
随机推荐
C语言联合体union占用空间大小问题
2021电赛资源及经验总结
TinyFlashDB:一种超轻量的可纠错的通用单片机flash存储方案
【论文精读】Rich Feature Hierarchies for Accurate Object Detection and Semantic Segmentation(R-CNN)
flink项目开发-flink的scala shell命令行交互模式开发
九、响应处理——内容协商底层原理
Facial Motion Capture 调研
【ts】typescript高阶:映射类型与keyof
【Multisim仿真】直流稳压电源设计报告
[Practice 1] Diabetes Genetic Risk Detection Challenge [IFLYTEK Open Platform]
【Over 15】A week of learning lstm
Flutter 3.0升级内容,该如何与小程序结合
网络信息安全运营方法论 (上)
基于Flink CDC实现实时数据采集(二)-Source接口实现
PoE视频监控解决方案
11%的参数就能优于Swin,微软提出快速预训练蒸馏方法TinyViT
BFC详解(Block Formmating Context)
RecycleView和ViewPager2
[Database and SQL study notes] 10. (T-SQL language) functions, stored procedures, triggers
读论文- pix2pix