/** * A single {@code condition} that must be {@linkplain #matches matched} in order * for a component to be registered. * * <p>Conditions are checked immediately before the bean-definition is due to be * registered and are free to veto registration based on any criteria that can * be determined at that point. * * <p>Conditions must follow the same restrictions as {@link BeanFactoryPostProcessor} * and take care to never interact with bean instances. For more fine-grained control * of conditions that interact with {@code@Configuration} beans consider the * {@link ConfigurationCondition} interface. * * @author Phillip Webb * @since 4.0 * @see ConfigurationCondition * @see Conditional * @see ConditionContext */ @FunctionalInterface publicinterfaceCondition {
/** * Determine if the condition matches. * @param context the condition context * @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class} * or {@link org.springframework.core.type.MethodMetadata method} being checked * @return {@code true} if the condition matches and the component can be registered, * or {@code false} to veto the annotated component's registration */ booleanmatches(ConditionContext context, AnnotatedTypeMetadata metadata);
publicabstractclassSpringBootConditionimplementsCondition { @Override publicfinalbooleanmatches(ConditionContext context, AnnotatedTypeMetadata metadata) { //从封装condition注解信息的类中获取指定的Condition类的实现类 StringclassOrMethodName= getClassOrMethodName(metadata); try { //确定匹配结果以及日志输出对象 ConditionOutcomeoutcome= getMatchOutcome(context, metadata); //打印匹配的情况,如果是不匹配会打印不匹配的原因 logOutcome(classOrMethodName, outcome); //将匹配结果进行存储 recordEvaluation(context, classOrMethodName, outcome); //返回匹配的结果 return outcome.isMatch(); } catch (NoClassDefFoundError ex) { thrownewIllegalStateException("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) { thrownewIllegalStateException("Error processing condition on " + getName(metadata), ex); } }
/** * The classes that must be present. Since this annotation is parsed by loading class * bytecode, it is safe to specify classes here that may ultimately not be on the * classpath, only if this annotation is directly on the affected component and * <b>not</b> if this annotation is used as a composed, meta-annotation. In order to * use this annotation as a meta-annotation, only use the {@link #name} attribute. * @return the classes that must be present */ Class<?>[] value() default {};
/** * The classes names that must be present. * @return the class names that must be present. */ String[] name() default {};
@Override publicfinalbooleanmatches(ConditionContext context, AnnotatedTypeMetadata metadata) { //获取加上了@ConditionalOnClass注解的类或者方法的名称(我们就以类分析,加在方法上是一个原理) StringclassOrMethodName= getClassOrMethodName(metadata); try { // 典型的钩子方法,调到用具体子类中方法。ConditionOutcome 这个类里面包装了是否需 // 跳过和打印的日志 ConditionOutcomeoutcome= getMatchOutcome(context, metadata); logOutcome(classOrMethodName, outcome); recordEvaluation(context, classOrMethodName, outcome); return outcome.isMatch(); } catch (NoClassDefFoundError ex) { thrownewIllegalStateException("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) { thrownewIllegalStateException("Error processing condition on " + getName(metadata), ex); } }
/** * The class types of beans that should be checked. The condition matches when beans * of all classes specified are contained in the {@link BeanFactory}. * @return the class types of beans to check */ Class<?>[] value() default {};
/** * The class type names of beans that should be checked. The condition matches when * beans of all classes specified are contained in the {@link BeanFactory}. * @return the class type names of beans to check */ String[] type() default {};
/** * The annotation type decorating a bean that should be checked. The condition matches * when all of the annotations specified are defined on beans in the * {@link BeanFactory}. * @return the class-level annotation types to check */ Class<? extendsAnnotation>[] annotation() default {};
/** * The names of beans to check. The condition matches when all of the bean names * specified are contained in the {@link BeanFactory}. * @return the names of beans to check */ String[] name() default {};
/** * Strategy to decide if the application context hierarchy (parent contexts) should be * considered. * @return the search strategy */ SearchStrategy search()default SearchStrategy.ALL;
/** * Additional classes that may contain the specified bean types within their generic * parameters. For example, an annotation declaring {@code value=Name.class} and * {@code parameterizedContainer=NameRegistration.class} would detect both * {@code Name} and {@code NameRegistration<Name>}. * @return the container types * @since 2.1.0 */ Class<?>[] parameterizedContainer() default {};