Solon v3.0.3

@Condition 用法说明

</> markdown

满足条件的,才会被配置或构建。v2.1.4 后支持

属性说明
onClass有类(只能一个;其实没必要多个)
onClassName有类名
onProperty有属性
onMissingBean没有 Bean
onMissingBeanName没有 Bean Name
onBean有 Bean。v2.9 后支持
onBeanName有 Bean Name。v2.9 后支持

关于“onClass”和“onClassName”:

  • 检测类的本质其实是检查对应的依赖包是否引入了
  • 同一个依赖包内的类,用一个即可;不同依赖包的类,建议分开检测

关于“onProperty”,有三种用法:

  • "${yyy.enable}",有属性即可
  • "${yyy.enable} = true",有属性且=true(只支持=号,简单才高效;复杂的手写)
  • "${yyy.enable:true} = true",没属性(通过默认值加持)或者有属性且=true

1、加在 @Bean 函数上

@Bean 函数可以返回 null,有些复杂的条件可以在函数内处理。

@Configuration
public class DemoConfig{
    //检查否类有类存在,然后再产生它的bean
    @Bean
    //@Condition(onClassName="org.aaa.IXxxAaaImpl") //有类名
    @Condition(onClass=IXxxAaaImpl.class)  //有类
    public IXxx getXxx(){
        return new IXxxAaaImpl();
    }

    //检查有配置存在,然后再产生对应的bean
    @Bean
    //@Condition(onProperty="${yyy.enable}") //有属性值
    @Condition(onProperty="${yyy.enable} = true") //有属性值,且等于true
    public IYyy getYyy(@Inject("${yyy.config}") IYyyImpl yyy){
        return yyy;
    }
}

2、加在组件类上(任何组件类)

使用 onClass 条件时,组件不能继承自检测类。不然获取类元信息时直接会异常

@Condition(onClass=XxxDemo.class) 
@Configuration
public class DemoConfig{ //DemoConfig 不能扩展自 XxxDemo
}

@Condition(onClass=XxxDemo.class) 
@Component
public class DemoCom{ //DemoCom 不能扩展自 XxxDemo
}
  • 实例
@Condition(onClass = SaSsoManager.class)
@Configuration
public class SaSsoAutoConfigure {
    @Bean
    public SaSsoConfig getConfig(@Inject(value = "${sa-token.sso}", required = false) SaSsoConfig ssoConfig) {
        return ssoConfig;
    }
    
    @Bean
    public void setSaSsoConfig(@Inject(required = false) SaSsoConfig saSsoConfig) {
        SaSsoManager.setConfig(saSsoConfig);
    }
    
    @Bean
    public void setSaSsoTemplate(@Inject(required = false) SaSsoTemplate ssoTemplate) {
        SaSsoUtil.ssoTemplate = ssoTemplate;
        SaSsoProcessor.instance.ssoTemplate = ssoTemplate;
    }
}

3、onMissingBean 条件与 List[Bean] 注入的边界

  • onMissingBean 条件的执行时机为,Bean 扫描完成并检查之后才执行的
  • List[Bean](或 Map[String, Bean]) 注入,也是在 Bean 扫描完成后尝试注入的。
@Configuration
public class TestConfig{
    @Condition(onMissingBean = Xxx.class)
    @Bean
    public Xxx aaa(){
        ...
    }

    @Condition(onMissingBean = Yyy.class)
    @Bean
    public Yyy bbb(List<Xxx> xxxList ){
        ...
    }

    @Condition(onMissingBean = Zzz.class)
    @Bean
    public Zzz ccc(List<Yyy> yyyList ){
        ...
    }
}

在 v2.8.0 之前,还有谁未完成注册?是不可知的(没有做依赖探测)。像上面的示例,xxxList 是好的,yyyList 可能会傻掉。xxxList 和 yyyList 是相同的注入时机(谁先谁后,无序),此时 Yyy 因为依赖 xxxList,所以并未生成。

以上注解方式,也可以采用手写方式处理:

@Component
public class TestConfig implements LifecycleBean {
    @Inject
    AppContext context;

    @Override
    public void start() throws Throwable {
        if(!context.hasWrap(Xxx.class)){
            context.wrapAndPut(Xxx.class, new Xxx());
        }

        if(!context.hasWrap(Yyy.class)){
            List<Xxx> xxxList = context.getBeansOfType(Xxx.class);
            context.wrapAndPut(Yyy.class, new Yyy(xxxList));
        }

        if(!context.hasWrap(Zzz.class)){
            List<Yyy> yyyList = context.getBeansOfType(Yyy.class);
            context.wrapAndPut(Zzz.class, new Zzz(yyyList));
        }
    }
}