展露头脚
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提供的条件已经完全够用了)
网友评论