3 Core Notes
Open any * AutoConfiguration file, there are generally the following condition annotations, in the spring-boot-autoconfigure-1.5.3.RELEASE.jar package org.spring framework.boot.autoconfigure.condition conditions annotations are as follows:
- @ Conditional OnBean: The current container has a specified Bean condition.
- @ ConditionalOnClass: The condition under which a specified class exists under the current class path.
- @ Conditional On Expression: Based on SpEL expression as a judgment condition.
- @ Conditional On Java: Based on the JVM version as a criterion.
- @ Conditional On Jndi: Find the specified location in the presence of JNDI.
- @ Conditional On Missing Bean: When no Bean is specified in the container.
- @ Conditional OnMissing Class: When there is no specified class in the class path.
- @ Conditional OnNotWeb Application: The current project is not a WEB project.
- @ ConditionalOnProperty: Specifies whether the property has a specified value.
- @ ConditionalOnResource: Does the class path have a specified value?
- @ Conditional On Single Candidate: When there is only one specified Bean in the container, or if there are multiple but preferred beans.
- @ Conditional On Web Application: The current project is under the condition of a WEB project.
These annotations combine @Conditional meta-annotations, using only different conditions. Spring conditional annotation (@Conditional) We introduced creating different beans according to different conditions.
A brief analysis of the @ConditionalOnWeb Application annotation:
package org.springframework.boot.autoconfigure.condition;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnWebApplication {
}
From the source code, we can see that the condition for this annotation is the OnWebApplicationCondition class. Let's see how this class is constructed:
package org.springframework.boot.autoconfigure.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.StandardServletEnvironment;
@Order(Ordered.HIGHEST_PRECEDENCE + 20)
class OnWebApplicationCondition extends SpringBootCondition {
private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context."
+ "support.GenericWebApplicationContext";
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
boolean webApplicationRequired = metadata
.isAnnotated(ConditionalOnWebApplication.class.getName());
ConditionOutcome webApplication = isWebApplication(context, metadata);
if (webApplicationRequired && !webApplication.isMatch()) {
return ConditionOutcome.noMatch(webApplication.getMessage());
}
if (!webApplicationRequired && webApplication.isMatch()) {
return ConditionOutcome.noMatch(webApplication.getMessage());
}
return ConditionOutcome.match(webApplication.getMessage());
}
private ConditionOutcome isWebApplication(ConditionContext context,
AnnotatedTypeMetadata metadata) {
if (!ClassUtils.isPresent(WEB_CONTEXT_CLASS, context.getClassLoader())) {
return ConditionOutcome.noMatch("web application classes not found");
}
if (context.getBeanFactory() != null) {
String[] scopes = context.getBeanFactory().getRegisteredScopeNames();
if (ObjectUtils.containsElement(scopes, "session")) {
return ConditionOutcome.match("found web application 'session' scope");
}
}
if (context.getEnvironment() instanceof StandardServletEnvironment) {
return ConditionOutcome
.match("found web application StandardServletEnvironment");
}
if (context.getResourceLoader() instanceof WebApplicationContext) {
return ConditionOutcome.match("found web application WebApplicationContext");
}
return ConditionOutcome.noMatch("not a web application");
}
}
As can be seen from the isWeb Application method, the criteria are:
- Whether Generic Web Application Context is in the class path or not;
- Is there a scope called session in the container?
- Is the Enviroment of the current container Standard Servlet Environment?
- Whether the current ResourceLoader is a Web Application Context (ResourceLoader is one of the top-level interfaces of Application Context);
- We need to build an object of the ConditionOutcome class to help us determine the condition through the return value of the ConditionOutcome.isMatch method.