美文网首页
springboot 条件装配

springboot 条件装配

作者: MikeLi666 | 来源:发表于2019-07-24 17:35 被阅读0次

展露头脚

springboot的一大特点就是方便,今天来看看 @Condition 带给我们什么样的方便。

首先来写一个接口。

public interface AService {

    void test();

}

接下来调用接口

@SpringBootApplication
public class Application {

    public static void main(String[] args) {

        ConfigurableApplicationContext run = SpringApplication.run(Application.class);

        AService bean = run.getBean(AService.class);

        bean.test();

    }
    
}

接下来就差实现 AService 了,我希望有三种不同的实现。

@Service()
public class AService1 implements AService {
    public void test() {
        System.out.println("AService1");
    }
}
@Service()
public class AService2 implements AService{
    public void test() {
        System.out.println("AService2");
    }
}
@Service()
public class DefaultAService implements AService {
    public void test() {
        System.out.println("DefaultAService");
    }
}

我们先来运行一下

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'playground.service.AService' available: expected single matching bean but found 3: AService1,AService2,defaultAService

因为有三个不同的实现类,spring没法明白我们到底要把哪个加入到容器中,当调用AService的test方法时,用哪一个。

所以需求场景,就变成了,我可以在配置文件中二选一(AService1,AService2),如果没有选就用默认的。

这里主要用到三个注解

@ConditionalOnProperty()
@Service()
@ConditionalOnMissingBean()

如果在配置文件中找到 AServiceType = 1 的配置,那么就载入一个 name = AService type=AService1 的bean到ioc容器。

@ConditionalOnProperty(value = "AServiceType", havingValue = "1")
@Service("AService")
public class AService1 implements AService {
    public void test() {
        System.out.println("AService1");
    }
}

如果在配置文件中找到 AServiceType = 2 的配置,那么就载入一个 name = AService type=AService2 的bean到ioc容器。

@ConditionalOnProperty(value = "AServiceType", havingValue = "2")
@Service("AService")
public class AService2 implements AService {
    public void test() {
        System.out.println("AService2");
    }
}

如果没有发现 name=AService 的bean的话,则加载一个type=DefaultAService的bean到ioc容器。

@ConditionalOnMissingBean(name = "AService")
@Service
public class DefaultAService implements AService {
    public void test() {
        System.out.println("DefaultAService");
    }
}

如果 application.properties 没有 AServiceType=(1 or 2)

output : DefaultAService

如果 application.properties 中 AServiceType=1

output : AService1

如果 application.properties 中 AServiceType=2

output : AService2

可以看到 @Conditional 的功能,就是在不同条件下,指导加载器,要构建哪些bean加入到ioc容器。

先来看看@Conditional的部分派生

@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)
其他略 都是@Conditional*

那么当已有功能不能满足你的残暴需求的时候,怎么办呢?
我们随便点开两个@Conditional的派生注解看看

@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean

@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty

OnBeanCondition.class ,OnPropertyCondition.class
最终都是实现 Condition 接口,然后再上面做各种不同的扩展。
代码有点多,这里就不贴了。说白了我们可以自定义条件,实现Condition接口,来定制复杂的加载条件。(我觉得springboot提供的条件已经完全够用了)

相关文章

网友评论

      本文标题:springboot 条件装配

      本文链接:https://www.haomeiwen.com/subject/farfrctx.html