@Conditional相关注解
一、@Conditional
@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件的才给容器注册Bean。
代码例子:
package com.cy.conditional; /** * @description com.cy.conditional * @author: chengyu * @date: 2022-04-22 11:20 */ public interface ListService { public String showListCmd(); }
package com.cy.conditional; /** * @description com.cy.conditional * @author: chengyu * @date: 2022-04-22 11:21 */ public class LinuxListService implements ListService{ @Override public String showListCmd() { return "ls"; } }
package com.cy.conditional; /** * @description com.cy.conditional * @author: chengyu * @date: 2022-04-22 11:21 */ public class WindowsListService implements ListService{ @Override public String showListCmd() { return "dir"; } }
WindowsCondition:
package com.cy.conditional; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; /** * @description com.cy.conditional * @author: chengyu * @date: 2022-04-22 11:20 */ public class WindowsCondition implements Condition { @Override public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) { return arg0.getEnvironment().getProperty("os.name").contains("Windows"); } }
LinuxCondition:
package com.cy.conditional; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; /** * @description com.cy.conditional * @author: chengyu * @date: 2022-04-22 11:19 */ public class LinuxCondition implements Condition { @Override public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) { return arg0.getEnvironment().getProperty("os.name").contains("Linux"); } }
配置类Config:
package com.cy.conditional; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; /** * @description com.cy.conditional * @author: chengyu * @date: 2022-04-22 11:21 */ @Configuration public class ConditionConfig { @Bean @Conditional(WindowsCondition.class) public ListService windowsListService() { return new WindowsListService(); } @Bean @Conditional(LinuxCondition.class) public ListService linuxListService() { return new LinuxListService(); } }
测试类:
package com.cy.conditional; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @description com.cy.conditional * @author: chengyu * @date: 2022-04-22 11:22 */ public class App { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext( ConditionConfig.class); ListService ls = context.getBean(ListService.class); System.out.println(context.getEnvironment().getProperty("os.name") + "系统下的列表命令为:" + ls.showListCmd()); } }
console:
Windows 10系统下的列表命令为:dir
二、@ConditionalOnClass
例如:@ConditionalOnClass(KafkaTemplate.class)
表示:Spring工程中引用了Kafka的包 才会构建这个bean。就是说只有在classpath下能找到kafkaTemplate类才会构建这个bean。
三、@ConditionalOnBean
@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
参考博客:https://www.cnblogs.com/qdhxhz/p/11027546.html
代码例子:
1.实体类:
package com.cy.model; import lombok.Getter; import lombok.Setter; import lombok.ToString; /** * @description com.cy.model * @author: chengyu * @date: 2022-04-22 11:40 */ @Setter @Getter @ToString public class Mother { String name; int age; Son son; }
package com.cy.model; import lombok.Getter; import lombok.Setter; import lombok.ToString; /** * @description com.cy.model * @author: chengyu * @date: 2022-04-22 11:40 */ @Setter @Getter @ToString public class Son { String name; int age; }
2.配置类:
package com.cy.conditional; import com.cy.model.Mother; import com.cy.model.Son; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ConditionConfig { /*@Bean public Son son(){ Son s = new Son(); s.setAge(10); s.setName("小明"); return s; }*/ @Bean @ConditionalOnBean(Son.class) public Mother mother(Son son){ Mother m = new Mother(); m.setAge(40); m.setName("小慧妈妈"); m.setSon(son); return m; } }
3.测试类:
package com.cy.conditional; import com.cy.model.Mother; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * @description com.cy.conditional * @author: chengyu * @date: 2022-04-22 11:37 */ @Controller @Slf4j public class ConditionController { @Autowired(required = false) private Mother mother; @ResponseBody @RequestMapping("/testConditionOnBean") public void conditionOnBean() { System.out.println(mother); } }
4.测试结果:
a.当不存在Son实体类被注入时,如果private Mother mother上面直接是@Autowired时,启动就会报错:
Field mother in com.cy.conditional.ConditionController required a bean of type 'com.cy.model.Mother' that could not be found.
因此需要在@Autowired后面写上(required=false),required=false 的意思就是允许当前的Bean对象为null。正常启动后打印:null
b.当打开Son @Bean的注释后,重新启动,控制台打印:
Mother(name=小慧妈妈, age=40, son=Son(name=小明, age=10))
四、其他的
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)
五、@ConditionalOnProperty
@ConditionalOnProperty(prefix="person" name = "super.enable", matchIfMissing = false, havingValue = "true") 代表什么意思呢?
也是控制配置类是否生效;配置为:person.super.enable
prefix: 配置文件的前缀
name: 配置的名字,name或value是必填项。
havingValue: 与配置的值对比值,当两个值相同返回true,配置类生效。
matchIfMissing: 当未找到对应配置是否匹配,默认不匹配。该属性为true时,配置文件中缺少对应的value或name的对应的属性值,也会注入成功。
例如:@ConditionalOnProperty(prefix = "aspectLog", name = "enable",havingValue = "true", matchIfMissing = true)当配置文件有aspectLog.enable=true时开启,如果配置文件没有设置aspectLog.enable也开启。
---