该内容是在学习SpringBoot底层的时候,看到SpringBoot的使用,所以这的做一个简单的总结方便以后复习。可能会有一些问题,还望指出共同学习
@Conditional注解:
- 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring的IOC容器中。
- 位置:方法、类
- @Conditional本身是一个父注解,派生出大量的子注解:
- @ConditionalOnClass:注解用于基于类路径(Classpath)的条件装配
- @ConditionalOnBean 注解会检查 IOC 容器中是否存在一个或多个指定的 Bean,只有在满足条件的情况下才会进行后续的自动配置
- @ConditionalOnMissingBean:判断ioc中没有对应的bean(类型或名称),才注册bean到IOC容器。
- @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。
下面就对@Conditional注解较常用的派生注解来做一个解释:
解释之前先对测试的结构做一个了解:
- 包结构
-
每个类的代码
- pojo包
/** * Parent类 */ public class Parent { } // /** * Child类 */ public class Child { } / /** * 其他类 */ public class Others { }
- 配置类
/** * 配置文件,对Bean的处理 */ @Configuration public class BeanConfig { @Bean public Child getChild(){ return new Child(); } }
@ConditionalOnClass
@ConditionalOnClass 注解用于基于类路径(Classpath)的条件装配,即根据某个类是否存在于 classpath 中进行条件判断,从而控制 Spring Boot 应用中 Bean(组件)是否需要被创建。
具体来说,@ConditionalOnClass 注解会检查指定类路径中的指定的类是否存在,如果该类在 Classpath 中,则会将当前的Bean放入到IOC容器中。反之,如果指定类没有存在于 Classpath 则不会 创建当前的Bean
常用的属性有:
-
name:需要是全路径类名,多个类名称使用逗号分隔。当有多个类名称,那么必须所有的类都存在时才会创建当前的Bean。
-
value : 会判断Classpath中是否有指定的字节码文件,如果有多个只有当都满足的情况才会创建当前Bean
@Bean @ConditionalOnClass(name = {"com.yfs1024.pojo.Parent","com.yfs1024.pojo.Others"}) public Child getChild(){ return new Child(); }
当两个都存在时Spring会将当前@Bean注解修饰的方法的返回放入IOC容器,名字为方法名(下面就不在赘述)
- 通过可视化界面可以看到,高亮部分是Spring默认生成,没有高亮是我们自己写的类
如果其中一个类不存在就不创建如图 2;
对于通过类型判断(注解中的value可以省略),也是如此,判断的是在编译之后有没有对应的字节码文件,代码如下:
@Bean
@ConditionalOnClass({Parent.class, Others.class})
public Child getChild(){
return new Child();
}
此时编译之后的Classpath文件存在这两个文件的字节码文件,所以会将这个Bean放入到容器中。结果如图1;
@ConditionalOnBean
@ConditionalOnBean 它的作用是根据 Bean 的条件来控制某些 Bean 的加载和初始化。它可以被用于方法上面,表示只有在指定类型的 Bean 存在时才会进行方法的调用。也可以用于类上面,表示只有在指定类型的 Bean 存在时,该类才会被加载和初始化。
这个注解的参数常用的应该也是那两个 name:value : 当然还有type,annotation, 这里就不再介绍,等我用到了再补充
// Class<?>[] value() default {}; 当参数为value是传入的需要是字节码文件,即Class类的对象
/
@Bean
@ConditionalOnBean({Parent.class, Others.class})
public Child getChild(){
return new Child();
}
此时因为IOC容器中并没有这个字节码类对象的两个对象,容器中的图如图2所示;
现在我们在Parent和Others上添加@Component注解让Spring扫描到,此时,容器中就有了这两个对象,如下,所以当前的方法的返回值就会放入到容器中。结果如图1所示:修改Parent和Others代码如下:
@Component
public class Others {
}
//
@Component
public class Parent {
}
另外也可以通过名称来限定是否创建,但是在此时可能就出现容器中并没有加入当前对象,即容器中没有getChild这个对象,但是有Others和Parent这两个对象的现象。此时我们就可以通过自己指定,来确定顺序。
原因: 这是因为在判断的时候其他的两个对象还没有创建
@Bean
@ConditionalOnBean(name = "getParent")
public Child getChild(){
return new Child();
}
此时我们就可以通过自己指定,来确定顺序。
@Bean
public Parent getParent(){
return new Parent();
}
@Bean
@ConditionalOnBean(name = "getParent")
public Child getChild(){
return new Child();
}
此时再看就有了。解决。所以在这里也推荐使用value参数,较好。
@ConditionalOnMissingBean
当IOC容器 中不存在指定类型的Bean时,才会加载该Bean,否则将会忽略这个Bean。
常见的使用场景是:当某个类不存在时才创建对应的 Bean。
@Bean
public Parent getParent(){
return new Parent();
}
@Bean
@ConditionalOnMissingBean(name = "getPar2ent")
public Child getChild(){
return new Child();
}
此时会创建因为容器中没有getPar2ent
这个对象,如下,但是当为getParent
,时就不会创建。
这个比较好理解,结果略过
@ConditionalOnProperty
@ConditionalOnProperty主要作用是根据应用程序的配置属性来决定是否创建 Bean.
常见的使用场景是:根据配置来控制某些 Bean 是否启用或者禁用,从而实现应用程序的灵活性和可配置性。
@ConditionalOnProperty 注解可以根据一或多个配置属性的值来决定是否创建 Bean,配置属性的值可以是 true、false、null、或者一个具体的字符串。
例如,我们需要根据某个配置属性来判断是否创建一个 Bean,可以这样写:
application.properties
配置文件中
aliyun:
oss:
endpoint: hangzhou.aliyuncs
@Bean
@ConditionalOnProperty("aliyun.oss.endpoint")
public Others getOthers(){
return new Others();
}
即当配置文件中有aliyun.oss.endpoint 这个配置的时候才创建当前的对象。结果如图
看到这里其实我们也就可以想到,为什么Mybatis在没有yml配置文件中配置时会报错,我猜就是这个原因
对于这个注解其中的几个参数就要学习一下了
- havingValue:指定配置属性的值与该属性值匹配时,创建 Bean,默认为 “”。
- matchIfMissing:指定当配置属性不存在时,是否创建 Bean,默认是 true。
- prefix:用于设置配置属性的前缀。
- name:用于指定配置属性的名称。
- value:用于指定配置属性的名称,与 name 属性类似。
- havingValue
@Bean
@ConditionalOnProperty(value = "aliyun.oss.endpoint" , havingValue = "hangzhou.aliyuncs")
public Others getOthers(){
return new Others();
}
此时因为我们指定的值和配置文件中的值相同,在此时就会创建当前的Bean
但是如果把后面的havingValue
修改的和配置文件中不一致时,此时就不会创建Bean,比如修改为havingValue = "yfs1024"
- boolean matchIfMissing() default false;
Spring给的解释:
Specify if the condition should match if the property is not set. Defaults to false.
Returns:
if the condition should match if the property is missing翻译:指定如果未设置属性,则条件是否应匹配。默认为 false。返回:如果缺少属性,条件是否匹配
比如说我们把代码修改一下,把matchIfMissing设置为true,此时表示,即使配置文件没有这个配置依然创建Bean。
注意:此时因为是多个参数,所以现在value就不可以省略了。
@Bean
@ConditionalOnProperty(value = "aliyun.oss.XXXX" , matchIfMissing=true)
public Others getOthers(){
return new Others();
}
- String prefix( ) default “”;
在上述示例中,我们使用了 “aliyun.oss” 作为配置属性的前缀。 application.yml配置如下:
aliyun:
oss:
enabled: true
那么就会创建一个 Others Bean。如果把 aliyun.oss.enabled 改成 false,或者删除该属性,Others 就不会被创建出来。
总之,@ConditionalOnProperty 注解的 prefix 属性可以指定配置属性的前缀,从而更好地管理和控制应用程序的配置属性。
先总结到这吧,睡觉