Spring boot源码分析-Conditional(12)

来源:互联网 发布:python 安卓 编辑:程序博客网 时间:2024/05/19 14:36

Spring boot源码分析-Conditional(12)

  • Condition是spring4.0增加的条件判断接口,用于判断条件满足情况,目前在spring中使用Conditional有两个地方

    1. 在注册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