不少人在使用 @ConditionalOnBean 注解时会遇到不生效的情况,依赖的 bean 明明已经配置了,但就是不生效。...是不是@ConditionalOnBean和 Bean加载的顺序有没有关系呢? 本篇文章就针对这个问题,跟着源码,一探究竟。...---- 问题演示: @Configuration public class Configuration1 { @Bean @ConditionalOnBean(Bean2.class...class Configuration2 { @Bean public Bean2 bean2(){ return new Bean2(); } } 运行结果: @ConditionalOnBean...---- 总结 在配置类中定义Bean,如果使用@ConditionalOnBean注解依赖的Bean是通过配置类触发解析的,则执行结果依赖配置类加载顺序 ### 更多阅读 [史上最简单的 SpringCloud
除了前面一篇博文中介绍的通过@Conditional注解配合Condition接口的实现之外,还提供了更多简化的注解使用方式,省略了自己实现Condtion接口,本篇博文主要介绍下面几个常用的注解使用方式 @ConditionalOnBean...@ConditionalOnBean 要求bean存在时,才会创建这个bean;如我提供了一个bean名为RedisOperBean,用于封装redis相关的操作;但是我这个bean需要依赖restTemplate...这个bean,只有当应用引入了redis的相关依赖,并存在RestTemplate这个bean的时候,我这个bean才会生效 假设bean的定义如下 @Component @ConditionalOnBean...Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) public @interface ConditionalOnBean...DependedBean(); } /** * 只有当DependedBean 存在时,才会创建bean: `LoadIfBeanExist` * * @return */ @Bean @ConditionalOnBean
@ConditionalOnBean:当容器中存在指定的 Bean 时,条件才会成立。 @ConditionalOnMissingBean:当容器中不存在指定的 Bean 时,条件才会成立。...我们选择@ConditionalOnBean为例,分析一下springboot条件注解的视线原理,看一下@ConditionalOnBean实现: @Target({ ElementType.TYPE,...)) { Spec spec = new Spec(context, metadata, annotations, ConditionalOnBean.class...五、解决方案 想要解决上述问题,要保证配置类的解析和加载在依赖类之后,也就是使用@ConditionalOnBean注解的类的条件判定和注册必须要在依赖的类之后,可以参考一下方案。...注解的 @Bean 方法移到自动装配类中,这样就可以保证自动装配类中的 Bean 先被加载和注册,满足 @ConditionalOnBean 的条件要求。
System.out.println(string); System.out.println(System.lineSeparator()); } } 运行结果如下,成功获取到bean 2)@ConditionalOnBean...@ConditionalOnBean和@ConditionalOnMissingBean是相反对应的一组注解,看注解名称也可以看出来。...先来看看他们的使用,如下 @SpringBootApplication public class TestApplication { @Bean("conditionalOnBean")...@ConditionalOnBean(TestApplication.class) public String conditionalOnBean() { return "conditionalOnBean...Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) public @interface ConditionalOnBean
Set onBeanTypes = autoConfigurationMetadata.getSet(autoConfigurationClass, "ConditionalOnBean..."); outcomes[i] = getOutcome(onBeanTypes, ConditionalOnBean.class); if...注解处理我们来看看 ConditionalOnBean 注解处理逻辑的源码: if (annotations.isPresent(ConditionalOnBean.class)) {...Spec spec = new Spec(context, metadata, annotations, ConditionalOnBean.class);...如果存在 @ConditionalOnBean,则创建一个条件规范 Spec 对象,该类是从底层的注解中提取的搜索规范;接着,调用 getMatchingBeans 方法,并从上下文【context】中获取与条件规范
package com.tianyalei.condition; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean...ConditionalOnClass true"); // return new Abc(); // } /** * 存在Abc类的实例时 */ @ConditionalOnBean...(Abc.class) @Bean public String bean() { System.err.println("ConditionalOnBean is exist...ConditionalOnMissingBean(Abc.class) @Bean public String missBean() { System.err.println("ConditionalOnBean...这句代码可以标注在类上面,表示该类下面的所有@Bean都会启用配置 也可以标注在方法上面,只是对该方法启用配置 除了自己自定义Condition之外,Spring还提供了很多Condition给我们用 @ConditionalOnBean
比如: @ConditionalOnBean、 @ConditionalOnClass、 @ConditionalOnExpression、 @ConditionalOnMissingBean等。...())) { BeanSearchSpec spec = new BeanSearchSpec(context, metadata, ConditionalOnBean.class...); // 构造一个BeanSearchSpec,会从@ConditionalOnBean注解中获取属性,然后设置到BeanSearchSpec中 List matching =...) { // 如果没有匹配的bean,返回一个没有匹配成功的ConditionalOutcome return ConditionOutcome .noMatch("@ConditionalOnBean..." + spec + " found no beans"); } // 如果找到匹配的bean,匹配信息进行记录 matchMessage.append( "@ConditionalOnBean
1.1.1 @ConditionalOnBean @ConditionalOnBean注解的作用是当注解参数对应的bean不存在时,则其标注的Bean也不会被注册。...此时再运行一下项目 此时发现user bean不存在(因为@Bean注解已经被注释掉了),并且book bean也不存在(@ConditionalOnBean注解的作用) 扩展: 使用@ConditionalOnBean...但这是如果调换一下两个bean的声明顺序,如下 此时得到如下结果: 可以看到book bean不能被创建,因为它是从上往下顺序注册到容器的的,在注册book时user bean还没被注册,@ConditionalOnBean...1.1.2 @ConditionalOnMissingBean 作用和@ConditionalOnBean相反 1.2. 配置绑定 1.2.1....这里打开CacheAutoConfiguration类查看 可以看到这里使用了@ConditionalOnClass,@ConditionalOnBean,@ConditionalOnMissingBean
同时是OnBeanCondition是@ConditionalOnBean,@ConditionalOnSingleCandidate和ConditionalOnMissingBean的条件类。...注解的情况 if (metadata.isAnnotated(ConditionalOnBean.class.getName())) { // 将@ConditionalOnBean注解属性封装进...BeanSearchSpec对象中 // 注意BeanSearchSpec是一个静态内部类,用来存储@ConditionalOnBean和@ConditionalOnMissingBean注解的属性值...BeanSearchSpec spec = new BeanSearchSpec(context, metadata, ConditionalOnBean.class); //...现在我们只看针对@ConditionalOnBean注解的处理逻辑,从上面代码中可以看到若配置类(metadata)标注@ConditionalOnBean注解的话,主要做了以下事情: 将该注解属性提取出来封装进
DiscoveryClientHealthIndicatorProperties.class) @ConditionalOnClass(HealthIndicator.class) @ConditionalOnBean...value = "spring.cloud.discovery.client.composite-indicator.enabled", matchIfMissing = true) @ConditionalOnBean...ConditionalOnClass(EurekaClientConfig.class) @Import(DiscoveryClientOptionalArgsConfiguration.class) @ConditionalOnBean
在SpringBoot中,@Conditional注解并不是孤军奋斗,它们是一个家族,我们来看一下它们其中的几个成员,又都是怎么用的 @ConditionalOnBean 示例代码 @...Bean@ConditionalOnBean(RedisConnectionFactory.class) public RedisTemplate redisTemplate...new StringRedisSerializer()); template.afterPropertiesSet(); return template; } 这个方法上加了@ConditionalOnBean
defaultLettuceConnectionFactory); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean @ConditionalOnBean...return new LettuceConnectionFactory(localRedisConfig, clientConfig); } @Bean @ConditionalOnBean...defaultLettuceConnectionFactory") LettuceConnectionFactory defaultLettuceConnectionFactory) { // .... } @Bean @ConditionalOnBean...RedisStandaloneConfiguration localRedisConfig, GenericObjectPoolConfig localPoolConfig) { // ... } @Bean @ConditionalOnBean
org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.condition.ConditionalOnBean...EnableAutoConfiguration(exclude = {RedisAutoConfiguration.class})public class RedisConfig { @Bean @ConditionalOnBean...org.springframework.boot.autoconfigure.AutoConfigureBefore;import org.springframework.boot.autoconfigure.condition.ConditionalOnBean...ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)public class ReactiveRedisConfig { @Bean @ConditionalOnBean
打开该类以后,在该类上有一个注解,该注解如下: @ConditionalOnBean({Marker.class}) 到这一步就基本可以确定是否加载 EurekaServerAutoConfiguration...回到 @EnableEurekaServer 注解前面的流程,有一个 @ConditionalOnBean 的注解,该注解就表示如果内存中有 Market.class 类,则加载 EurekaServerAutoConfiguration
@Configuration @ConditionalOnClass(DataSource.class) public class MySQLAutoconfiguration { } @ConditionalOnBean...@Bean @ConditionalOnBean(name = "dataSource") LocalContainerEntityManagerFactoryBean entityManagerFactory
Configuration @ConditionalOnClass(DataSource.class) class MySQLAutoconfiguration { //... } 4.2 @ConditionalOnBean...和@ConditionalOnMissingBean 当我们想要根据特定bean的存在与否来定义条件时,我们可以使用这些注释: @Bean @ConditionalOnBean(name = "dataSource
artifactId> 1.0-SNAPSHOT 3、Bean条件注解 Bean条件注解也是成对出现的,例如@ConditionalOnBean...Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) public @interface ConditionalOnBean...Servlet.class) public Formatter jsonFormatter(){ return new JsonFormatter(); } @Bean @ConditionalOnBean
Conditional又派生了许多注解,如下图: 下面以@ConditionalOnBean为例: 编写配置类MyConfig: import boot.bean.Pet; import boot.bean.User...; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean...new User("zhangsan",18); zhangsan.setPet(tomcatPet()); return zhangsan; } @ConditionalOnBean...import boot.bean.Pet; import boot.bean.User; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean...new User("zhangsan",18); zhangsan.setPet(tomcatPet()); return zhangsan; } @ConditionalOnBean
如图:当类上标识ConditionalOnBean,但是类又实现了BeanPostProcessor,那么此时的bean初始化有没有冲突呢?...1-ConditionalOnBean的功能:仅仅在当前上下文中存在某个对象时,才会实例化一个Bean,也就是下面的方法想要获取实例bean,需要先实例化 2-BeanPostProcessor:相当于切面...configClass.getImportBeanDefinitionRegistrars()); } if (configClass.isImported())当解析完注解解析时,beanDefinition已经被同步, 也就是ConditionalOnBean
领取专属 10元无门槛券
手把手带您无忧上云