<>@Conditional
Only when the specified conditions are met will a bean Load into application context .
such as FreemarkerAutoConfiguration This automation configuration class is defined as follows :
@ConditionalOnClass(ThreadPoolTaskScheduler.class) @Configuration
@EnableConfigurationProperties(TaskSchedulingProperties.class)
@AutoConfigureAfter(TaskExecutionAutoConfiguration.class) public class
TaskSchedulingAutoConfiguration { // ... }
This automation configuration class is @ConditionalOnClass Conditional annotation decoration ,
The significance of this conditional annotation is to determine whether it exists in the class loader ThreadPoolTaskScheduler This class ,
If it exists, it will Spring Load this in the container TaskSchedulingAutoConfiguration Configuration class , Otherwise, it will not be loaded .
<>@ConditionalOnXxxx
Spring Boot stay @Conditional Detailed on the basis of annotation , No need to implement Condition Interface , Just use the predefined
@ConditionalOnXxxx class , If the verification is passed , Will register the corresponding bean.
These annotations are defined in org.springframework.boot.autoconfigure.condition Under the package .
ConditionalOnBean ConditionalOnClass ConditionalOnCloudPlatform
ConditionalOnExpression ConditionalOnJava ConditionalOnJndi
ConditionalOnMissingBean ConditionalOnMissingClass
ConditionalOnNotWebApplication ConditionalOnProperty ConditionalOnResource
ConditionalOnSingleCandidate ConditionalOnWebApplication @Target({ElementType.
TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented
@Conditional(OnBeanCondition.class) public @interface ConditionalOnBean { // ...
}
<>spring-boot Condition Annotation corresponding to processing Conditional class
Condition (org.springframework.context.annotation) ConfigurationCondition (org.
springframework.context.annotation) AbstractNestedCondition (org.springframework
.boot.autoconfigure.condition) AllNestedConditions (org.springframework.boot.
autoconfigure.condition) NoneNestedConditions (org.springframework.boot.
autoconfigure.condition) AnyNestedCondition (org.springframework.boot.
autoconfigure.condition) OnBeanCondition (org.springframework.boot.autoconfigure
.condition)
<>Condition Interface
<>ConfigurationCondition Interface
One more getConfigurationPhase() method , that is Effective stage of condition notes . Only in ConfigurationPhase
Will only take effect in the two stages defined in .
<>SpringBootCondition
SpringBoot All condition classes corresponding to condition annotations in inherit this abstract class .
<>OnClassCondition
@ConditionalOnClass perhaps @ConditionalOnMissingClass The condition class corresponding to the annotation is OnClassCondition
<> entrance
1.ComponentScan scanning basePackage Lower components When , Will call
isConditionMatch(metadataReader) Judge the component Whether conditions match . By calling
conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata()) Determine whether to
skip The component.
2.// TODO
<> call
conditionEvaluator.shouldSkip() 1. Judgment must have @Conditional annotation 2. Judge whether there is phase 3. adopt
metadata Get all on this class Conditional annotation 4. Traversal through conditionClassName Get the corresponding Condition class
5. yes conditions sort 6. ergodic conditions, If ConfigurationCondition type , call
getConfigurationPhase() method , call condition.matches() method
SpringBootCondition.matches() 1.getClassOrMethodName() from metadata Get the class name or method name from the
( On the class or method that the conditional annotation can act on ) 2.getMatchOutcome(): Abstract method , Concrete subclass implementation . ConditionOutcome Match results recorded and
log information By specific Condition The implementation class of the interface implements the logic , as OnClassCondition, OnExpressionCondition etc.
// OnClassCondition.getMatchOutcome() See also Following logic 3.logOutcome(): Print Matching information journal
4.recordEvaluation(): record Matching information result 5.outcome.isMatch(): Return matching results
<>OnClassCondition.getMatchOutcome()
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) { ClassLoader classLoader = context.
getClassLoader(); ConditionMessage matchMessage = ConditionMessage.empty(); List
<String> onClasses = getCandidates(metadata, ConditionalOnClass.class); //
1.ConditionalOnClass Annotation Processing . Get on class @ConditionalOnClass Condition value in annotation . If from
@ConditionalOnClass({ Servlet.class, ServerContainer.class }) Get from
Servlet.class, ServerContainer.class if (onClasses != null) { List<String>
missing= filter(onClasses, ClassNameFilter.MISSING, classLoader); // Judge whether the condition class exists ,
Nonexistent add to missing in if (!missing.isEmpty()) { // With or without conditions return ConditionOutcome .
noMatch(ConditionMessage.forCondition(ConditionalOnClass.class) .didNotFind(
"required class", "required classes") .items(Style.QUOTE, missing)); // Mismatch
condition } matchMessage = matchMessage.andCondition(ConditionalOnClass.class) .
found("required class", "required classes").items(Style.QUOTE, filter(onClasses,
ClassNameFilter.PRESENT, classLoader)); // matching condition } List<String>
onMissingClasses= getCandidates(metadata, ConditionalOnMissingClass.class); //
2. ConditionalOnMissingClass Annotation Processing if (onMissingClasses != null) { List<String>
present= filter(onMissingClasses, ClassNameFilter.PRESENT, classLoader); if (!
present.isEmpty()) { return ConditionOutcome.noMatch( ConditionMessage.
forCondition(ConditionalOnMissingClass.class) .found("unwanted class",
"unwanted classes") .items(Style.QUOTE, present)); } matchMessage = matchMessage
.andCondition(ConditionalOnMissingClass.class) .didNotFind("unwanted class",
"unwanted classes") .items(Style.QUOTE, filter(onMissingClasses, ClassNameFilter
.MISSING, classLoader)); } return ConditionOutcome.match(matchMessage); } yes
ConditionalOnClass and ConditionalOnMissingClass Annotation processing . 1. yes ConditionalOnClass
Annotation processing 1. Get on class @ConditionalOnClass Condition value in annotation . If from
@ConditionalOnClass({Servlet.class, ServerContainer.class}) Get from Servlet.class,
ServerContainer.class 2.filter(onClasses, ClassNameFilter.MISSING, classLoader)
adopt ter.MISSING this filter Filter out nonexistent classes ( Pass immediately classLoader Cannot load ) 3. Return matching results 2. yes
ConditionalOnMissingClass Annotation processing Same logic as above
Technology