Spring Boot Operating Principles - Core Annotations

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:

  1. Whether Generic Web Application Context is in the class path or not;
  2. Is there a scope called session in the container?
  3. Is the Enviroment of the current container Standard Servlet Environment?
  4. Whether the current ResourceLoader is a Web Application Context (ResourceLoader is one of the top-level interfaces of Application Context);
  5. 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.

Keywords: Java Spring Session jvm

Added by linus on Sat, 06 Jul 2019 00:16:56 +0300