⭐**简单说两句**⭐
**✨ 正在努力的小新~**
**💖 超级爱分享,分享各种有趣干货!**
**👩💻 提供:模拟面试 | 简历诊断 | 独家简历模板**
**🌈 感谢关注,关注了你就是我的超级粉丝啦!**
**🔒 以下内容仅对你可见~**
<font color='#20afdf'>**作者:**</font>**不正经小新**,**CSDN后端领域新星创作者 |阿里云专家博主**
<font color='#f00f6d'>**CSDN**个人主页</font>:不正经小新
🔎**GZH**:
不正经小新
🎉<font color='#2979ff'>欢迎关注</font>🔎<font color='#ff69b4'>点赞</font>👍<font color='#ba2bec'>收藏</font>⭐️<font color='#fd700'>留言</font>📝
@toc
说在前面
本系列文章是Spring学习笔记,参考书 《SpringBoot源码解读与原理分析》
阅读的一个小要求:**至少会使用SpringBoot或Spring或者天才型选手**
本系列文章将会持续更新,更新速度取决于各位读者大大的<font color =#9642cd>点赞收藏和留言</font>
思维导图
为了方便读者了解文章整体内容,我给出了一张思维导图,希望有所帮助
Spring框架是一个开源的Java平台,它提供了全面的基础设施支持,用于创建Java应用程序。在Spring框架中,条件装配(Conditional Wiring)是一种基于条件的配置技术,它允许开发者根据不同的条件来决定是否创建某个Bean或者使用某个配置类。
概念:
条件装配的核心思想是让Spring容器在运行时根据特定的条件来决定是否装配(创建和配置)某个Bean。这些条件可以是基于类的存在、环境属性、表达式的计算结果等。
作用:
1、环境特定的配置:在不同的环境(开发、测试、生产)中,可能需要不同的Bean配置。条件装配允许开发者为不同的环境定义特定的Bean,而不需要在代码中硬编码这些差异。
2、特性开关:通过条件装配,可以根据是否包含某个特性来决定是否装配相关的Bean。这在实现功能开关时非常有用,可以在不修改代码的情况下,通过配置来开启或关闭某些功能。
3、优化性能:如果某些Bean只在特定的条件下需要,那么在其他条件下不创建这些Bean可以节省资源,提高应用性能。
4、模块化:条件装配支持应用的模块化设计,不同的模块可以根据需要独立配置,而不会相互干扰。
5、简化配置:在大型应用中,条件装配可以帮助减少配置的复杂性,通过集中管理条件逻辑,而不是在多个地方重复相同的配置。
在Spring3.1中,已经引入了Profile的概念,我们看下Spring源码中的描述:
@Profile可以以下列任何方式使用注解:
简单来说就是:Profile提供了一种“基于环境的配置”:根据当前项目的不同运行时环境,可以动态的注册与当前运行环境匹配的组件~
我们现在来实战一下Profile这个注解~
需求背景:调酒师只会在城市中工作,在荒郊野外的时候,调酒师不会进行工作。
分析:我们在代码层面就是在调酒师的配置类上加一个@Profile注解
BartenderConfiguration调酒师配置类 代码清单
@Configuration
@Profile("city")
public class BartenderConfiguration {
@Bean
public Bartender getBartender() {
return new Bartender("调酒师-01");
}
@Bean
public Bartender getBartender02() {
return new Bartender("调酒师-02");
}
}
为ApplicationContext设置Profile
@Test
public void testProfile() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("city");
context.register(BartenderConfiguration.class);
context.refresh();
String[] beanDefinitionNames = context.getBeanDefinitionNames();
Stream.of(beanDefinitionNames).forEach(log::info);
}
运行看结果
这段Java代码用于测试Spring框架中的配置文件激活功能。具体功能如下:
【提示】:AnnotationConfigApplicationContext在创建对象时,如果直接传入了配置类,则会立即初始化IOC容器,在不传入配置类的情况下,内部不会执行初始化逻辑,而是要等到手动调用refresh方法才会初始化IOC容器,在初始化的过程中,会顺带将环境配置一起处理~
flowchart TD
A[创建上下文实例] --> B[设置活动配置文件为 city]
B --> C[注册配置类 BartenderConfiguration]
C --> D[刷新上下文]
D --> E[获取所有 Bean 定义名称]
E --> F[遍历并输出 Bean 名称]
可以一些读者已经发现问题所在了,在上面的代码中,我们的环境是在代码中显示指定的,如果哪天需要重新更换,还得改代码重新部署,就麻烦了~
其实啊,Spring框架早就给我们考虑了这种情况,所以还提供了一些其他的方式,比如命令行参数配置~
我们看下怎么配置,在Spring源码中可以找到这个,就是通过spring.profiles.active来传递的~
我们在代码中注释掉context.getEnvironment().setActiveProfiles("city");
然后再Idea中设置命令行启动参数~
点击运行后,同样发现还是打印了我们的调酒师~
Profile机制在SpringBoot中运用的也很经典,使用spring.profiles.active可以指定环境配置application.properties文件可以通过添加后缀来区分不同环境,比如 application-dev.properties、application-test.properties等等~
虽然Profile很牛掰,但是也是有缺点的,比如:吧台中需要有老板或负责人,如果都没的话,那么吧台就不应该存在~,这个时候Profile就不太好实现了,因为Profile是控制的整个项目的运行环境,没办法根据单个Bean来决定是否装配 ~
那怎么解决这个问题呢?
Spring其实也给我们想到了,给我们提供了另一个注解:@Conditional
@Conditional是在Spring4.0版本中推出的,他可以让Bean注册到IOC容器时,必须满足@Conditional上的条件~
来,接着奏乐,接着舞,我们简单实现下上面的需求:吧台需要依赖老板的存在~
思路分析:
我们先编写判断Boss类是否存在的判断类,怎么写呢,我们直接实现Condition的接口,然后看容器中是否存在Boss类就OK了~
ExistBossConditon代码清单
public class ExistBossConditon implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getBeanFactory().containsBeanDefinition(Boss.class.getName());
}
}
BarConfiguration代码清单
@Configuration
public class BarConfiguration {
@Conditional(ExistBossConditon.class)
@Bean
public Bar bbar() {
return new Bar();
}
}
EnableTavern注解代码清单
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({Boss.class, BartenderConfiguration.class})
public @interface EnableTavern {
}
TavernConfiguration代码清单
@Configuration
@EnableTavern
public class TavernConfiguration {
}
测试类代码清单
@Test
public void testConditional() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(TavernConfiguration.class, BarConfiguration.class);
context.refresh();
String[] beanDefinitionNames = context.getBeanDefinitionNames();
Stream.of(beanDefinitionNames).forEach(log::info);
}
运行结果
SpringBoot中对Conditional注解进行了一些扩展
比如:
<font color='#f00f6d'>【都看到这了,点点赞点点关注呗,爱你们】</font>😚😚
💬
**✨ 正在努力的小新~**
**💖 超级爱分享,分享各种有趣干货!**
**👩💻 提供:模拟面试 | 简历诊断 | 独家简历模板**
**🌈 感谢关注,关注了你就是我的超级粉丝啦!**
**🔒 以下内容仅对你可见~**
<font color='#20afdf'>**作者:**</font>**不正经小新**,**CSDN后端领域新星创作者 |阿里云专家博主**
<font color='#f00f6d'>**CSDN**个人主页</font>:不正经小新
🔎**GZH**:不正经小新
🎉<font color='#2979ff'>欢迎关注</font>🔎<font color='#ff69b4'>点赞</font>👍<font color='#ba2bec'>收藏</font>⭐️<font color='#fd700'>留言</font>📝
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。