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:
Phillip Webb 2013-08-14 17:08:09 -07:00 committed by Phillip Webb
parent c9b3af09b4
commit 840fdeb50f
9 changed files with 301 additions and 326 deletions

View File

@ -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();
}
}

View File

@ -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) {

View File

@ -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,

View File

@ -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());
}
}

View File

@ -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) {

View File

@ -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");
}
}

View File

@ -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);
}
}
}

View File

@ -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");
}
}
}

View File

@ -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);
}
}