博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot conditional注解和自定义conditional注解使用
阅读量:1982 次
发布时间:2019-04-27

本文共 5722 字,大约阅读时间需要 19 分钟。

conditional注解是Springboot starter的基石,自动装配的时候会根据条件确定是否需要注入这个类。

含义:基于条件的注解。

作用:根据是否满足某个特定条件来决定是否创建某个特定的Bean。

意义:Springboot实现自动配置的关键基础能力。

@ConditionalOnBean:仅仅在当前上下文中存在某个对象时,才会实例化一个Bean

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

 

配置文件有这个配置

spring.data.mongodb.uri=mongodb://paopaoedu:paopaoedu@localhost:27017/paopaoedu

判断有这个配置才注入这个类 

package com.paopaoedu.springboot.condition;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.stereotype.Component;@Component@ConditionalOnProperty("spring.data.mongodb.uri")public class ConditionalTest {}

 

测试文件

package com.paopaoedu.springboot;import com.paopaoedu.springboot.condition.ConditionalTest;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.BeansException;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTest(classes = {SpringBootLearningApplication.class})//不用类似new ClassPathXmlApplicationContext()的方式,从已有的spring上下文取得已实例化的bean。通过ApplicationContextAware接口进行实现。public class SpringBootLearningApplicationTests implements ApplicationContextAware {    private ApplicationContext applicationContext;    @Override    public void setApplicationContext(ApplicationContext context) throws BeansException {        applicationContext = context;    }    @Test    public void testA() {        System.out.println("testA>>>"+applicationContext.getBean(ConditionalTest.class));    }}

关于ApplicationContextAware使用理解参考

可以看出这个ConditionalTest被注入了:

如果你去掉这个配置测试用例就会报错找不到这个bean:

自定义conditional注解实现

 

自定义注解引入condition接口实现类

@Target({ ElementType.TYPE, ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)@Documented@Conditional(MyCondition.class)public @interface MyConditionAnnotation {    String[] value() default {};}

实现一个自定义注解

实现Condition接口重写matches方法,符合条件返回true

public class MyCondition implements Condition {    @Override    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        String[] properties = (String[])metadata.getAnnotationAttributes("com.paopaoedu.springboot.condition.MyConditionAnnotation").get("value");        for (String property : properties) {            if (StringUtils.isEmpty(context.getEnvironment().getProperty(property))) {                return false;            }        }        return true;    }}

引入conditional注解

@Component@MyConditionAnnotation({"spring.redis.master.host", "spring.redis.follow.host"})public class ConditionalTest2 {}

配置文件

# Redis服务器地址spring.redis.master.host=r-xxx1.redis.rds.aliyuncs.com# Redis服务器连接端口spring.redis.master.port=6379# Redis服务器连接密码(默认为空)spring.redis.master.password=# Redis服务器地址spring.redis.follow.host=r-xxx2.redis.rds.aliyuncs.com# Redis服务器连接端口spring.redis.follow.port=6379# Redis服务器连接密码(默认为空)spring.redis.follow.password=

修改测试用例

@RunWith(SpringRunner.class)@SpringBootTest(classes = {SpringBootLearningApplication.class})//不用类似new ClassPathXmlApplicationContext()的方式,从已有的spring上下文取得已实例化的bean。通过ApplicationContextAware接口进行实现。public class SpringBootLearningApplicationTests implements ApplicationContextAware {    private ApplicationContext applicationContext;    @Override    public void setApplicationContext(ApplicationContext context) throws BeansException {        applicationContext = context;    }    @Test    public void testA() {        System.out.println("testA>>>"+applicationContext.getBean(ConditionalTest.class));        System.out.println("testA>>>"+applicationContext.getBean(ConditionalTest2.class));    }}

输出

 

重要的调试断点ClassPathScanningCandidateComponentProvider.scanCandidateComponents()

private Set
scanCandidateComponents(String basePackage) { Set
candidates = new LinkedHashSet<>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }

转载地址:http://hlrpf.baihongyu.com/

你可能感兴趣的文章
单目深度估计 monodepth2模型 代码
查看>>
搜索中的TSA(树搜索算法) & GSA(图搜索算法) & UCS(代价一致) & CSP(约束满足问题)
查看>>
位图索引Bitmap indexes
查看>>
YOLO算法(二)—— Yolov2 & yolo9000
查看>>
YOLO算法(三)—— Yolov3 & Yolo系列网络优缺点
查看>>
Python的__future__模块
查看>>
Paper reading —— Semantic Stereo Matching with Pyramid Cost Volumes(SSPCV-Net)
查看>>
计算机视觉中的cost-volume的概念具体指什么(代价体积)
查看>>
Paper reading——Pyramid Stereo Matching Network(PSM-Net)
查看>>
启发函数heuristic 与 A*
查看>>
Image Pyramid(图像金字塔)
查看>>
Oracle 作业记录
查看>>
putty连接AWS配置(multimedia project)
查看>>
Hourglass Network 沙漏网络 (pose estimation姿态估计)
查看>>
OpenCV实战(二)——答题卡识别判卷
查看>>
目标检测神经网络的发展历程(52 个目标检测模型)
查看>>
Boundary loss 损失函数
查看>>
神经网络调参实战(一)—— 训练更多次数 & tensorboard & finetune
查看>>
tensorflow使用tensorboard进行可视化
查看>>
神经网络调参实战(二)—— activation & initializer & optimizer
查看>>