聊聊SpringBoot自动装配的魔力
一、 springBoot自动配置的好处
1、 回想一下当你在使用spring来搭建一个项目的时候
你需要编写很多的有关spring的xml。例如读取属性配置的bean、数据源bean、事务管理工厂bean、mybatis与spring整个的bean等等。再次利用该框架搭建项目的时候,又是周而复始的操作。
但是现在当你使用springBoot搭建项目的时候,你会发现所有的配置你都不用去编写就可以帮你去实现(仅仅需要在连接外部数据库的时候需要进行配置,其实如果使用内嵌数据库h2 则你完全不必需要application.properties配置文件)。
你可以在你的具体的业务代码中使用@AutoWried @Resource注解将数据源,事务工厂等注入到业务层,像是你自己配置那样。
2、这时我们会有一个疑问
springBoot到底做了什么让我们可以不用配置,而使用那些功能对象。
其实springBoot使用基于条件的自动注入原理,即为当满足某个条件的时候,spring会实例化该注解对应的bean,将其放入到Srping上下文中,让你可以轻松的使用。SpringBoot实现条件配置离不开它的核心组件@Conditional。
下面我们慢慢的来揭开springBoot自动配置的神秘面纱。
二、@Conditional注解相关介绍
1、@Conditional小demo
@Conditional 是个什么鬼,不解释来个小的demo大致了解一下
描述一下demo场景 :Life实体bean在特定条件(@Conditional)下,被springBoot初始化,并放置到spring上下文环境中。
1.1、 Life 实体类
public class Life {
//工作
private String work;
//学习
private String study
//爱
private String love;
//省略seter /geter
}
1.2、 编写我们自己的条件匹配规则
public class MyTestConditional implements ConfigurationCondition {
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.REGISTER_BEAN;
}
@Override
public boolean matches(ConditionContext conditionContext,
AnnotatedTypeMetadata annotatedTypeMetadata) {
return false; //表示验证不通过
}
该类实现了ConfigurationCondition 有如下两个方法
1、 getConfigurationPhase() 该条件规则起作用的时候
2、 matches()条件匹配规则 这里为了演示不做具体的逻辑条件的处理
返回一个布尔值,如果为ture 则表示条件成立 配置生效
反之不生效。
1.3、编写我们的java实例bean自动配置
@Configuration
//@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans>,
// 作用为:配置spring容器(应用上下文)
public class ServerAutoConfiguration {
@Configuration //spring的xml配置文件中的<beans>
//使用该注解表明,在springBoot启动的时候只有满足MyTestConditional.class 才生成对应的Life 对象
//即 MyTestConditional中的match()返回true @Bean生效
@Conditional(MyTestConditional.class)
public static class StudentAutoConfiguration {
@Bean
public Life create() {
System.out.println("life start....");
return new Life("努力工作","不断的学习","敢爱敢恨");
}
}
}
1.4、 springBoot的单元测试
//使用Spring的单元测试环境
@RunWith(SpringRunner.class)
//将SpringBoot的上下文环境加载进入单元测试中
@SpringBootTest(classes = AutoApplication.class)
public class AutoApplicationTests {
//注入springBoot 基于条件的实例化bean
@Autowired
private Life life;
@Test
public void showlife() {
System.out.println("生命的全部:"+life.toString());
}
}
启动springBoot项目,在控制台中没有发现Life对象被创建 且单元测试中无法注入Life
在修改了MyTestConditional中的match() 返回true 再次启动则Life对象被创建
同时使用SpringBoot的单元测试来使用springBoot为我们设置的Life实体
该实体创建流程如下:当springBoot项目启动的时候,会加载@Configuration(srping的xml配置)下的所有bean,当遇到@Conditional(MyTestConditional.class) 会调用该方法的Match,并根据其返回值来判断是否实例化该注解下的所有使用@Bean @Import 注解下的类
三、自定义一个条件配置类/springBoot自定义注解
1、简单解释@Condition注解家族
(1)、@Conditional
官方文档定义:
“Indicates that a component is only eligible for registration when all specified conditions match”
意思是只有满足一些列条件之后创建一个bean。 并注册到spring的上下文环境中
(2)、SpringBoot提供的
@ConditionalOnWebApplication
该应用必须为web应用@ConditionalOnMissingBean
该应用上下文中如果没有指定的bean@ConditionalOnBean
该应用上下文中如果有指定的bean@ConditionalOnProperty(name,value)
只有存在对应name的value的配置文件才加载该注解下的bean@ConditionalOnCloudPlatform
匹配当处于云平台环境中时后@ConditionalOnClass
该classpath中如果有指定的bean @ConditionalOnExpression 如果对应的表达式成立 成功@ConditionalOnJava
根据应用程序运行的JVM版本进行匹配 成功@ConditionalOnRepositoryType
当特定类型的spring Data JPA启用的时候 成功@ConditionalOnSingleCandidate
当特定的class对应的bean存在且唯一确定的时候@ConditionalOnJndi
通过JNDI查找制定的条件@Profile
通过特定的条件触发 (生产环境使用该配置,非生产环境则不是使用)@ConditionalOnResource
从资源文件中查询@ConditionalOnEnabledResourceChain
从资源链中中查询@ConditionalOnNotWebApplication
如果改应用不是web应用,则该条件起作用@ConditionalOnMissingClass
如果不存在对应的class则创建该对应的bean
满足条件后则加载该注解作用下的类起作用
(3)、所谓该注解作用下的类起作用是指
这些注解都有如下两种使用方式
1、作用在类上,则该类下的所有@Bean注解起作用 (条件成立,加载该注解下的所有@Bean的实体类 存放在spring上下文中)
2、作用在方法上 则该方法下对应的@bean注解起作用 (条件成立,加载该注解下使用@Bean的实体类 存放在spring上下文中)
与@Configuration或者@Bean配合使用,当和@Configuration配合使用时,
那么该类下所有@Bean方法 或者@Import 或者 @ComponentScan都会受到其配置条件的影响
@Configuration
相当于spring的xml配置文件的<beans>标签@Bean
注解相当于spring的xml配置文件的<bean>标签@Import(Xxx.class)
将指定的class 实例注入到spring的上下文中@Configuration
标注在类上,相当于把该类作为spring的xml配置文件中的<beans>,作用为:配置spring容器(应用上下文)
2、自定义条件注解
结合demo 来设置一个自定义注解
(1)、 自定义注解
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(MyTestConditional.class)
public @interface ConditionalOnLife {
Class<?>[] value() default {};
String[] name() default {};}
(2)、进行配置使用
@Configuration //spring的xml配置文件中的<beans>
//使用该注解表明,在springBoot启动的时候只有满足MyTestConditional.class 才生成对应的Life 对象
//自定义的条件注解
@ConditionalOnLife
//@Conditional(MyTestConditional.class)
public static class DreamAutoConfiguration {
@Bean
public Dream createDream() {
//life.toString();
System.out.println("dream start....");
return new Dream();
}
}
后台调用成功创建了Dream实体 并放入spring上下文环境中
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341