Spring boot源码分析-Conditional(12)
来源:互联网 发布:python 安卓 编辑:程序博客网 时间:2024/05/19 14:36
Spring boot源码分析-Conditional(12)
Condition是spring4.0增加的条件判断接口,用于判断条件满足情况,目前在spring中使用Conditional有两个地方
- 在注册bean的时候会拿Condition判断是否这个是一个满足条件应该注册的bean
AnnotatedBeanDefinitionReader.registerBean
/* * 这个方法其实是把自己给注册上了(在AnnotationConfigApplicationContext启动的时候) */ @SuppressWarnings("unchecked") public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) { //支持元数据的beandefinition一般实现 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); //this is new StandardAnnotationMetadata(beanClass, true); //注解判断 如果有注解元数据并且注解元数据还没满足条件 返回true 那么就不注册这个配置文件了 //这里好像说的是 配置类可以写几个一样的 在不同的环境上进行原型 传入统一参数就好了 //abd.getMetadata() 标准封装的注解元素 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } //获取封装完成的scopeMetadata 有可能没有这个注解 直接回来标准的 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); //创建ScopedProxyMode代理 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }
ClassPathScanningCandidateComponentProvider.findCandidateComponents
/** * Scan the class path for candidate components. * @param basePackage the package to check for annotated classes * @return a corresponding Set of autodetected bean definitions * 扫描得到候选组件 */ public Set<BeanDefinition> findCandidateComponents(String basePackage) { ...... //满足是一个组件的所有要求 if (isCandidateComponent(metadataReader)) { //生成ScannedGenericBeanDefinition其实就是一个带有注解信息,没有任何构造函数参数等等的GenericBeanDefinition ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); //判断是否给定的beandefinition是一个具体的类,不是接口或者抽象类 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); } } } ...... return candidates; }
private boolean isConditionMatch(MetadataReader metadataReader) { if (this.conditionEvaluator == null) { this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), getResourceLoader()); } return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata()); }
2. 在Spring按照Configuration类的方式进行配置的时候,会加载解析Configuration组件类,加载的时候会调用Condition的子类ConfigurationCondition去判断是否需要解析Configuration或者是否注册Bean(查看ConfigurationClassPostProcessor)
- ConfigurationCondition增加了解释的方式判断,Condition判断的扩展,在解析Configuration的时候使用
public interface ConfigurationCondition extends Condition { ConfigurationPhase getConfigurationPhase(); public static enum ConfigurationPhase { PARSE_CONFIGURATION, REGISTER_BEAN }}
- SpringBootCondition实现了Condition的抽象类,提供动态类加载功能,提供了日志和诊断功能
public abstract class SpringBootCondition implements Condition { private final Log logger = LogFactory.getLog(getClass()); @Override public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { String classOrMethodName = getClassOrMethodName(metadata); try { ConditionOutcome outcome = getMatchOutcome(context, metadata); logOutcome(classOrMethodName, outcome); recordEvaluation(context, classOrMethodName, outcome); return outcome.isMatch(); } catch (NoClassDefFoundError ex) { throw new IllegalStateException( "Could not evaluate condition on " + classOrMethodName + " due to " + ex.getMessage() + " not " + "found. Make sure your own configuration does not rely on " + "that class. This can also happen if you are " + "@ComponentScanning a springframework package (e.g. if you " + "put a @ComponentScan in the default package by mistake)", ex); } catch (RuntimeException ex) { throw new IllegalStateException( "Error processing condition on " + getName(metadata), ex); } } private String getName(AnnotatedTypeMetadata metadata) { if (metadata instanceof AnnotationMetadata) { return ((AnnotationMetadata) metadata).getClassName(); } if (metadata instanceof MethodMetadata) { MethodMetadata methodMetadata = (MethodMetadata) metadata; return methodMetadata.getDeclaringClassName() + "." + methodMetadata.getMethodName(); } return metadata.toString(); } private static String getClassOrMethodName(AnnotatedTypeMetadata metadata) { if (metadata instanceof ClassMetadata) { ClassMetadata classMetadata = (ClassMetadata) metadata; return classMetadata.getClassName(); } MethodMetadata methodMetadata = (MethodMetadata) metadata; return methodMetadata.getDeclaringClassName() + "#" + methodMetadata.getMethodName(); } private void logOutcome(String classOrMethodName, ConditionOutcome outcome) { if (this.logger.isTraceEnabled()) { this.logger.trace(getLogMessage(classOrMethodName, outcome)); } } private StringBuilder getLogMessage(String classOrMethodName, ConditionOutcome outcome) { StringBuilder message = new StringBuilder(); message.append("Condition "); message.append(ClassUtils.getShortName(getClass())); message.append(" on "); message.append(classOrMethodName); message.append(outcome.isMatch() ? " matched" : " did not match"); if (StringUtils.hasLength(outcome.getMessage())) { message.append(" due to "); message.append(outcome.getMessage()); } return message; } private void recordEvaluation(ConditionContext context, String classOrMethodName, ConditionOutcome outcome) { if (context.getBeanFactory() != null) { ConditionEvaluationReport.get(context.getBeanFactory()) .recordConditionEvaluation(classOrMethodName, this, outcome); } } /** * Determine the outcome of the match along with suitable log output. * @param context the condition context * @param metadata the annotation metadata * @return the condition outcome */ public abstract ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata); /** * Return true if any of the specified conditions match. * @param context the context * @param metadata the annotation meta-data * @param conditions conditions to test * @return {@code true} if any condition matches. */ protected final boolean anyMatches(ConditionContext context, AnnotatedTypeMetadata metadata, Condition... conditions) { for (Condition condition : conditions) { if (matches(context, metadata, condition)) { return true; } } return false; } /** * Return true if any of the specified condition matches. * @param context the context * @param metadata the annotation meta-data * @param condition condition to test * @return {@code true} if the condition matches. */ protected final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata, Condition condition) { if (condition instanceof SpringBootCondition) { return ((SpringBootCondition) condition).getMatchOutcome(context, metadata) .isMatch(); } return condition.matches(context, metadata); }}
阅读全文
0 0
- Spring boot源码分析-Conditional(12)
- springboot 1.5.3 源码分析(三):spring @Conditional注解
- Spring Boot 源码分析
- Spring-boot中Conditional介绍
- Spring boot源码分析-BeanDefinitionLoader(7)
- Spring boot源码分析-starter(10)
- Spring boot源码分析-ConfigurationProperties
- springboot 1.5.3 源码分析(四):自定义Conditional注解
- Spring Boot起步依赖源码分析(一)
- Spring Boot起步依赖源码分析(二)
- Spring boot源码分析-SpringApplication启动(1)
- Spring boot源码分析-profiles环境(4)
- Spring boot源码分析-ApplicationListener应用环境(5)
- Spring boot源码分析-log日志系统(6)
- Spring boot源码分析-SpringBootApplication注解(8)
- Spring boot源码分析-yaml语言(9)
- Spring Boot启动过程源码分析(二)事件监听器
- spring-boot-admin源码分析及单机监控spring-boot-monitor的实现(一)
- Spring boot源码分析-ConfigurationProperties
- 如何使用Journalctl查看并操作Systemd日志
- 八、用户进程:TSS、用户进程的创建、用户进程的执行(通过调度函数)
- Java简单文件读写
- 块设备驱动
- Spring boot源码分析-Conditional(12)
- 软件工程学习总结
- 谁拿到了最多奖学金
- Android issue: adb install … 发生异常 [INSTALL_FAILED_TEST_ONLY: installPackageLI
- Java回调
- 接口切换
- jquery 验证 添加 批量删除
- GC是如何确定垃圾的?和垃圾回收算法
- 在 Linux 下搭建 Git 服务器