Create common SpringBootCondition base class
Create a new SpringBootCondition that will log why a condition has or has not been applied. The removes the need for ConditionLogUtils and simplifies many of the existing condition implementations. Issue: #55203236
This commit is contained in:
committed by
Phillip Webb
parent
c9b3af09b4
commit
840fdeb50f
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.condition;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.core.type.ClassMetadata;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
|
||||
/**
|
||||
* General utilities for constructing {@code @Conditional} log messages.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public abstract class ConditionLogUtils {
|
||||
|
||||
public static String getPrefix(Log logger, AnnotatedTypeMetadata metadata) {
|
||||
String prefix = "";
|
||||
if (logger.isDebugEnabled()) {
|
||||
prefix = metadata instanceof ClassMetadata ? "Processing "
|
||||
+ ((ClassMetadata) metadata).getClassName() + ". "
|
||||
: (metadata instanceof MethodMetadata ? "Processing "
|
||||
+ getMethodName((MethodMetadata) metadata) + ". " : "");
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
private static String getMethodName(MethodMetadata metadata) {
|
||||
return metadata.getDeclaringClassName() + "#" + metadata.getMethodName();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,8 +21,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
@@ -45,32 +43,25 @@ import org.springframework.util.ReflectionUtils.MethodCallback;
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
class OnBeanCondition implements ConfigurationCondition {
|
||||
class OnBeanCondition extends SpringBootCondition implements ConfigurationCondition {
|
||||
|
||||
private static final String[] NO_BEANS = {};
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Override
|
||||
public ConfigurationPhase getConfigurationPhase() {
|
||||
return ConfigurationPhase.REGISTER_BEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
|
||||
String checking = ConditionLogUtils.getPrefix(this.logger, metadata);
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
|
||||
if (metadata.isAnnotated(ConditionalOnBean.class.getName())) {
|
||||
BeanSearchSpec spec = new BeanSearchSpec(context, metadata,
|
||||
ConditionalOnBean.class);
|
||||
List<String> matching = getMatchingBeans(context, spec);
|
||||
if (matching.isEmpty()) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + " @ConditionalOnBean " + spec
|
||||
+ " found no beans (search terminated with matches=false)");
|
||||
}
|
||||
return false;
|
||||
return Outcome.noMatch("@ConditionalOnBean " + spec + " found no beans");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,16 +70,12 @@ class OnBeanCondition implements ConfigurationCondition {
|
||||
ConditionalOnMissingBean.class);
|
||||
List<String> matching = getMatchingBeans(context, spec);
|
||||
if (!matching.isEmpty()) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + " @ConditionalOnMissingBean " + spec
|
||||
+ " found the following " + matching
|
||||
+ " (search terminated with matches=false)");
|
||||
}
|
||||
return false;
|
||||
return Outcome.noMatch("@ConditionalOnMissingBean " + spec
|
||||
+ " found the following " + matching);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return Outcome.match();
|
||||
}
|
||||
|
||||
private List<String> getMatchingBeans(ConditionContext context, BeanSearchSpec beans) {
|
||||
|
||||
@@ -20,8 +20,6 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
@@ -36,14 +34,11 @@ import org.springframework.util.StringUtils;
|
||||
* @see ConditionalOnClass
|
||||
* @see ConditionalOnMissingClass
|
||||
*/
|
||||
class OnClassCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(OnClassCondition.class);
|
||||
class OnClassCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
|
||||
String checking = ConditionLogUtils.getPrefix(logger, metadata);
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
|
||||
MultiValueMap<String, Object> onClasses = getAttributes(metadata,
|
||||
ConditionalOnClass.class);
|
||||
@@ -51,13 +46,8 @@ class OnClassCondition implements Condition {
|
||||
List<String> missing = getMatchingClasses(onClasses, MatchType.MISSING,
|
||||
context);
|
||||
if (!missing.isEmpty()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking
|
||||
+ "Required @ConditionalOnClass classes not found: "
|
||||
+ StringUtils.collectionToCommaDelimitedString(missing)
|
||||
+ " (search terminated with matches=false)");
|
||||
}
|
||||
return false;
|
||||
return Outcome.noMatch("required @ConditionalOnClass classes not found: "
|
||||
+ StringUtils.collectionToCommaDelimitedString(missing));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,20 +57,12 @@ class OnClassCondition implements Condition {
|
||||
List<String> present = getMatchingClasses(onMissingClasses,
|
||||
MatchType.PRESENT, context);
|
||||
if (!present.isEmpty()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking
|
||||
+ "Required @ConditionalOnMissing classes found: "
|
||||
+ StringUtils.collectionToCommaDelimitedString(present)
|
||||
+ " (search terminated with matches=false)");
|
||||
}
|
||||
return false;
|
||||
return Outcome.noMatch("required @ConditionalOnMissing classes found: "
|
||||
+ StringUtils.collectionToCommaDelimitedString(present));
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "Match result is: true");
|
||||
}
|
||||
return true;
|
||||
return Outcome.match();
|
||||
}
|
||||
|
||||
private MultiValueMap<String, Object> getAttributes(AnnotatedTypeMetadata metadata,
|
||||
|
||||
@@ -16,12 +16,9 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.condition;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.expression.StandardBeanExpressionResolver;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
@@ -33,32 +30,21 @@ import org.springframework.core.type.ClassMetadata;
|
||||
* @author Dave Syer
|
||||
* @see ConditionalOnExpression
|
||||
*/
|
||||
public class OnExpressionCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(OnExpressionCondition.class);
|
||||
public class OnExpressionCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
|
||||
String checking = ConditionLogUtils.getPrefix(logger, metadata);
|
||||
|
||||
String value = (String) metadata.getAnnotationAttributes(
|
||||
String expression = (String) metadata.getAnnotationAttributes(
|
||||
ConditionalOnExpression.class.getName()).get("value");
|
||||
if (!value.startsWith("#{")) {
|
||||
if (!expression.startsWith("#{")) {
|
||||
// For convenience allow user to provide bare expression with no #{} wrapper
|
||||
value = "#{" + value + "}";
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
StringBuilder builder = new StringBuilder(checking)
|
||||
.append("Evaluating expression");
|
||||
if (metadata instanceof ClassMetadata) {
|
||||
builder.append(" on " + ((ClassMetadata) metadata).getClassName());
|
||||
}
|
||||
builder.append(": " + value);
|
||||
logger.debug(builder.toString());
|
||||
expression = "#{" + expression + "}";
|
||||
}
|
||||
|
||||
// Explicitly allow environment placeholders inside the expression
|
||||
value = context.getEnvironment().resolvePlaceholders(value);
|
||||
expression = context.getEnvironment().resolvePlaceholders(expression);
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
BeanExpressionResolver resolver = beanFactory.getBeanExpressionResolver();
|
||||
BeanExpressionContext expressionContext = (beanFactory != null) ? new BeanExpressionContext(
|
||||
@@ -66,11 +52,14 @@ public class OnExpressionCondition implements Condition {
|
||||
if (resolver == null) {
|
||||
resolver = new StandardBeanExpressionResolver();
|
||||
}
|
||||
boolean result = (Boolean) resolver.evaluate(value, expressionContext);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "Finished matching and result is matches=" + result);
|
||||
boolean result = (Boolean) resolver.evaluate(expression, expressionContext);
|
||||
|
||||
StringBuilder message = new StringBuilder("SpEL expression");
|
||||
if (metadata instanceof ClassMetadata) {
|
||||
message.append(" on " + ((ClassMetadata) metadata).getClassName());
|
||||
}
|
||||
return result;
|
||||
message.append(": " + expression);
|
||||
return new Outcome(result, message.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ package org.springframework.boot.autoconfigure.condition;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
@@ -35,43 +33,29 @@ import org.springframework.util.MultiValueMap;
|
||||
* @author Dave Syer
|
||||
* @see ConditionalOnResource
|
||||
*/
|
||||
class OnResourceCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(OnResourceCondition.class);
|
||||
class OnResourceCondition extends SpringBootCondition {
|
||||
|
||||
private ResourceLoader defaultResourceLoader = new DefaultResourceLoader();
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
|
||||
String checking = ConditionLogUtils.getPrefix(logger, metadata);
|
||||
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(
|
||||
ConditionalOnResource.class.getName(), true);
|
||||
ResourceLoader loader = context.getResourceLoader() == null ? this.defaultResourceLoader
|
||||
: context.getResourceLoader();
|
||||
if (attributes != null) {
|
||||
ResourceLoader loader = context.getResourceLoader() == null ? this.defaultResourceLoader
|
||||
: context.getResourceLoader();
|
||||
List<String> locations = new ArrayList<String>();
|
||||
collectValues(locations, attributes.get("resources"));
|
||||
Assert.isTrue(locations.size() > 0,
|
||||
"@ConditionalOnResource annotations must specify at least one resource location");
|
||||
for (String location : locations) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "Checking for resource: " + location);
|
||||
}
|
||||
if (!loader.getResource(location).exists()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "Resource not found: " + location
|
||||
+ " (search terminated with matches=false)");
|
||||
}
|
||||
return false;
|
||||
return Outcome.noMatch("resource not found: " + location);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "Match result is: true");
|
||||
}
|
||||
return true;
|
||||
return Outcome.match();
|
||||
}
|
||||
|
||||
private void collectValues(List<String> names, List<Object> values) {
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.condition;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
@@ -34,51 +32,46 @@ import org.springframework.web.context.support.StandardServletEnvironment;
|
||||
* @see ConditionalOnWebApplication
|
||||
* @see ConditionalOnNotWebApplication
|
||||
*/
|
||||
class OnWebApplicationCondition implements Condition {
|
||||
class OnWebApplicationCondition extends SpringBootCondition {
|
||||
|
||||
private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context.support.GenericWebApplicationContext";
|
||||
|
||||
private static Log logger = LogFactory.getLog(OnWebApplicationCondition.class);
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
boolean webContextRequired = metadata
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
boolean webApplicationRequired = metadata
|
||||
.isAnnotated(ConditionalOnWebApplication.class.getName());
|
||||
boolean webApplication = isWebApplication(context, metadata);
|
||||
return (webContextRequired ? webApplication : !webApplication);
|
||||
Outcome webApplication = isWebApplication(context, metadata);
|
||||
|
||||
if (webApplicationRequired && !webApplication.isMatch()) {
|
||||
return Outcome.noMatch(webApplication.getMessage());
|
||||
}
|
||||
|
||||
if (!webApplicationRequired && webApplication.isMatch()) {
|
||||
return Outcome.noMatch(webApplication.getMessage());
|
||||
}
|
||||
|
||||
return Outcome.match(webApplication.getMessage());
|
||||
}
|
||||
|
||||
private boolean isWebApplication(ConditionContext context,
|
||||
private Outcome isWebApplication(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
String checking = ConditionLogUtils.getPrefix(logger, metadata);
|
||||
|
||||
if (!ClassUtils.isPresent(WEB_CONTEXT_CLASS, context.getClassLoader())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "web application classes not found");
|
||||
}
|
||||
return false;
|
||||
return Outcome.noMatch("web application classes not found");
|
||||
}
|
||||
|
||||
if (context.getBeanFactory() != null) {
|
||||
String[] scopes = context.getBeanFactory().getRegisteredScopeNames();
|
||||
if (ObjectUtils.containsElement(scopes, "session")) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "found web application scope");
|
||||
}
|
||||
return true;
|
||||
return Outcome.match("found web application 'session' scope");
|
||||
}
|
||||
}
|
||||
|
||||
if (context.getEnvironment() instanceof StandardServletEnvironment) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "found web application environment");
|
||||
}
|
||||
return true;
|
||||
return Outcome.match("found web application StandardServletEnvironment");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "is not a web application");
|
||||
}
|
||||
return false;
|
||||
return Outcome.noMatch("not a web application");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.condition;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.core.type.ClassMetadata;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base of all {@link Condition} implementations used with Spring Boot. Provides sensible
|
||||
* logging to help the user diagnose what classes are loaded.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class SpringBootCondition implements Condition {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Override
|
||||
public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
Outcome result = getMatchOutcome(context, metadata);
|
||||
if (!result.isMatch()) {
|
||||
// Log non-matching conditions at debug
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(getMessage(metadata, result));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log matching conditions at trace
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(getMessage(metadata, result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private StringBuilder getMessage(AnnotatedTypeMetadata metadata, Outcome result) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append("Condition ");
|
||||
message.append(ClassUtils.getShortName(getClass()));
|
||||
message.append(" on ");
|
||||
if (metadata instanceof ClassMetadata) {
|
||||
ClassMetadata classMetadata = (ClassMetadata) metadata;
|
||||
message.append(classMetadata.getClassName());
|
||||
}
|
||||
else if (metadata instanceof MethodMetadata) {
|
||||
MethodMetadata methodMetadata = (MethodMetadata) metadata;
|
||||
message.append(methodMetadata.getDeclaringClassName());
|
||||
message.append("#");
|
||||
message.append(methodMetadata.getMethodName());
|
||||
}
|
||||
message.append(result.isMatch() ? " matched" : "did not match");
|
||||
if (StringUtils.hasLength(result.getMessage())) {
|
||||
message.append(" due to ");
|
||||
message.append(result.getMessage());
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the outcome of the match along with suitable log output.
|
||||
*/
|
||||
public abstract Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata);
|
||||
|
||||
protected final boolean anyMatches(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata, Condition... conditions) {
|
||||
for (Condition condition : conditions) {
|
||||
if (matches(context, metadata, condition)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outcome for a match, including log message.
|
||||
*/
|
||||
protected final static class Outcome {
|
||||
|
||||
private final boolean match;
|
||||
|
||||
private final String message;
|
||||
|
||||
public Outcome(boolean match, String message) {
|
||||
this.match = match;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public boolean isMatch() {
|
||||
return this.match;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public static Outcome match() {
|
||||
return match(null);
|
||||
}
|
||||
|
||||
public static Outcome match(String message) {
|
||||
return new Outcome(true, message);
|
||||
}
|
||||
|
||||
public static Outcome noMatch(String message) {
|
||||
return new Outcome(false, message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,9 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionLogUtils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
@@ -39,6 +39,7 @@ import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
@@ -55,6 +56,7 @@ import org.springframework.util.StringUtils;
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for {@link DataSource}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(EmbeddedDatabaseType.class /* Spring JDBC */)
|
||||
@@ -85,7 +87,7 @@ public class DataSourceAutoConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Conditional(DataSourceAutoConfiguration.SomeDatabaseCondition.class)
|
||||
@Conditional(DataSourceAutoConfiguration.DatabaseCondition.class)
|
||||
protected static class JdbcTemplateConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
@@ -134,119 +136,39 @@ public class DataSourceAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
static class SomeDatabaseCondition implements Condition {
|
||||
static abstract class NonEmbeddedDatabaseCondition extends SpringBootCondition {
|
||||
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Condition tomcatCondition = new TomcatDatabaseCondition();
|
||||
|
||||
private Condition dbcpCondition = new BasicDatabaseCondition();
|
||||
|
||||
private Condition embeddedCondition = new EmbeddedDatabaseCondition();
|
||||
protected abstract String getDataSourceClassName();
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
|
||||
String checking = ConditionLogUtils.getPrefix(this.logger, metadata);
|
||||
if (!ClassUtils.isPresent(getDataSourceClassName(), context.getClassLoader())) {
|
||||
return Outcome.noMatch(getDataSourceClassName()
|
||||
+ " DataSource class not found");
|
||||
}
|
||||
|
||||
if (this.tomcatCondition.matches(context, metadata)
|
||||
|| this.dbcpCondition.matches(context, metadata)
|
||||
|| this.embeddedCondition.matches(context, metadata)) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + "Existing auto database "
|
||||
+ "detected: match result true");
|
||||
}
|
||||
return true;
|
||||
String driverClassName = getDriverClassName(context.getEnvironment());
|
||||
if (driverClassName == null) {
|
||||
return Outcome.noMatch("no database driver");
|
||||
}
|
||||
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
context.getBeanFactory(), DataSource.class, true, false).length > 0) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + "Existing bean configured database "
|
||||
+ "detected: match result true");
|
||||
}
|
||||
return true;
|
||||
|
||||
String url = getUrl(context.getEnvironment());
|
||||
if (url == null) {
|
||||
return Outcome.noMatch("no database URL");
|
||||
}
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + "Existing bean configured database not "
|
||||
+ "detected: match result false");
|
||||
|
||||
if (ClassUtils.isPresent(driverClassName, context.getClassLoader())) {
|
||||
return Outcome.match("found database driver " + driverClassName);
|
||||
}
|
||||
return false;
|
||||
|
||||
return Outcome.match("missing database driver " + driverClassName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TomcatDatabaseCondition extends NonEmbeddedDatabaseCondition {
|
||||
|
||||
@Override
|
||||
protected String getDataSourecClassName() {
|
||||
return "org.apache.tomcat.jdbc.pool.DataSource";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class BasicDatabaseCondition extends NonEmbeddedDatabaseCondition {
|
||||
|
||||
private Condition condition = new TomcatDatabaseCondition();
|
||||
|
||||
@Override
|
||||
protected String getDataSourecClassName() {
|
||||
return "org.apache.commons.dbcp.BasicDataSource";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
if (this.condition.matches(context, metadata)) {
|
||||
return false; // prefer Tomcat pool
|
||||
}
|
||||
return super.matches(context, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class NonEmbeddedDatabaseCondition implements Condition {
|
||||
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected abstract String getDataSourecClassName();
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
|
||||
String checking = ConditionLogUtils.getPrefix(this.logger, metadata);
|
||||
|
||||
if (!ClassUtils.isPresent(getDataSourecClassName(), null)) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + "Tomcat DataSource pool not found");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String driverClassName = getDriverClassName(context, checking);
|
||||
String url = getUrl(context);
|
||||
|
||||
if (driverClassName != null && url != null
|
||||
&& ClassUtils.isPresent(driverClassName, null)) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + "Driver class " + driverClassName
|
||||
+ " found");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + "Driver class " + driverClassName
|
||||
+ " not found");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getDriverClassName(ConditionContext context, String checking) {
|
||||
String driverClassName = context.getEnvironment().getProperty(
|
||||
"spring.database.driverClassName");
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking
|
||||
+ "Spring JDBC detected (embedded database type is "
|
||||
+ EmbeddedDatabaseConfiguration.getEmbeddedDatabaseType() + ").");
|
||||
}
|
||||
private String getDriverClassName(Environment environment) {
|
||||
String driverClassName = environment == null ? null : environment
|
||||
.getProperty("spring.database.driverClassName");
|
||||
if (driverClassName == null) {
|
||||
driverClassName = EmbeddedDatabaseConfiguration
|
||||
.getEmbeddedDatabaseDriverClass(EmbeddedDatabaseConfiguration
|
||||
@@ -255,8 +177,9 @@ public class DataSourceAutoConfiguration {
|
||||
return driverClassName;
|
||||
}
|
||||
|
||||
private String getUrl(ConditionContext context) {
|
||||
String url = context.getEnvironment().getProperty("spring.database.url");
|
||||
private String getUrl(Environment environment) {
|
||||
String url = (environment == null ? null : environment
|
||||
.getProperty("spring.database.url"));
|
||||
if (url == null) {
|
||||
url = EmbeddedDatabaseConfiguration
|
||||
.getEmbeddedDatabaseUrl(EmbeddedDatabaseConfiguration
|
||||
@@ -266,34 +189,78 @@ public class DataSourceAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
static class EmbeddedDatabaseCondition implements Condition {
|
||||
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
static class BasicDatabaseCondition extends NonEmbeddedDatabaseCondition {
|
||||
|
||||
private Condition tomcatCondition = new TomcatDatabaseCondition();
|
||||
|
||||
private Condition dbcpCondition = new BasicDatabaseCondition();
|
||||
@Override
|
||||
protected String getDataSourceClassName() {
|
||||
return "org.apache.commons.dbcp.BasicDataSource";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
|
||||
String checking = ConditionLogUtils.getPrefix(this.logger, metadata);
|
||||
|
||||
if (this.tomcatCondition.matches(context, metadata)
|
||||
|| this.dbcpCondition.matches(context, metadata)) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking + "Existing non-embedded "
|
||||
+ "database detected: match result false");
|
||||
}
|
||||
return false;
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
if (matches(context, metadata, this.tomcatCondition)) {
|
||||
return Outcome.noMatch("tomcat DataSource");
|
||||
}
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(checking
|
||||
+ "Spring JDBC detected (embedded database type is "
|
||||
+ EmbeddedDatabaseConfiguration.getEmbeddedDatabaseType() + ").");
|
||||
}
|
||||
return EmbeddedDatabaseConfiguration.getEmbeddedDatabaseType() != null;
|
||||
return super.getMatchOutcome(context, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
static class TomcatDatabaseCondition extends NonEmbeddedDatabaseCondition {
|
||||
|
||||
@Override
|
||||
protected String getDataSourceClassName() {
|
||||
return "org.apache.tomcat.jdbc.pool.DataSource";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class EmbeddedDatabaseCondition extends SpringBootCondition {
|
||||
|
||||
private SpringBootCondition tomcatCondition = new TomcatDatabaseCondition();
|
||||
|
||||
private SpringBootCondition dbcpCondition = new BasicDatabaseCondition();
|
||||
|
||||
@Override
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
if (anyMatches(context, metadata, this.tomcatCondition, this.dbcpCondition)) {
|
||||
return Outcome.noMatch("existing non-embedded database detected");
|
||||
}
|
||||
EmbeddedDatabaseType type = EmbeddedDatabaseConfiguration
|
||||
.getEmbeddedDatabaseType();
|
||||
if (type == null) {
|
||||
return Outcome.noMatch("no embedded database detected");
|
||||
}
|
||||
return Outcome.match("embedded database " + type + " detected");
|
||||
}
|
||||
}
|
||||
|
||||
static class DatabaseCondition extends SpringBootCondition {
|
||||
|
||||
private SpringBootCondition tomcatCondition = new TomcatDatabaseCondition();
|
||||
|
||||
private SpringBootCondition dbcpCondition = new BasicDatabaseCondition();
|
||||
|
||||
private SpringBootCondition embeddedCondition = new EmbeddedDatabaseCondition();
|
||||
|
||||
@Override
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
|
||||
if (anyMatches(context, metadata, this.tomcatCondition, this.dbcpCondition,
|
||||
this.embeddedCondition)) {
|
||||
return Outcome.match("existing auto database detected");
|
||||
}
|
||||
|
||||
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
context.getBeanFactory(), DataSource.class, true, false).length > 0) {
|
||||
return Outcome.match("Existing bean configured database detected");
|
||||
}
|
||||
|
||||
return Outcome.noMatch("no existing bean configured database");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ import java.util.Arrays;
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -33,10 +31,10 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionLogUtils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration.EmbeddedServletContainerCustomizerBeanPostProcessorRegistrar;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
@@ -44,7 +42,6 @@ import org.springframework.boot.context.embedded.ServletContextInitializer;
|
||||
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -149,42 +146,24 @@ public class EmbeddedServletContainerAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private static class DefaultServletCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(DefaultServletCondition.class);
|
||||
private static class DefaultServletCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
|
||||
String checking = ConditionLogUtils.getPrefix(logger, metadata);
|
||||
public Outcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
String[] beans = beanFactory.getBeanNamesForType(DispatcherServlet.class,
|
||||
false, false);
|
||||
if (beans.length == 0) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking
|
||||
+ "No DispatcherServlet found (search terminated with matches=true)");
|
||||
}
|
||||
// No dispatcher servlet so no need to ask further questions
|
||||
return true;
|
||||
return Outcome.match("no DispatcherServlet found");
|
||||
}
|
||||
if (Arrays.asList(beans).contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking + "DispatcherServlet found and named "
|
||||
+ DEFAULT_DISPATCHER_SERVLET_BEAN_NAME
|
||||
+ " (search terminated with matches=false)");
|
||||
}
|
||||
// An existing bean with the default name
|
||||
return false;
|
||||
return Outcome.noMatch("found DispatcherServlet named "
|
||||
+ DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(checking
|
||||
+ "Multiple DispatcherServlets found and none is named "
|
||||
+ DEFAULT_DISPATCHER_SERVLET_BEAN_NAME
|
||||
+ " (search terminated with matches=true)");
|
||||
}
|
||||
return true;
|
||||
return Outcome.match("multiple DispatcherServlets found and none is named "
|
||||
+ DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user