diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java index a0610904b8..dfba242844 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -29,6 +29,7 @@ import org.springframework.core.type.AnnotatedTypeMetadata; * A Condition that evaluates a SpEL expression. * * @author Dave Syer + * @author Stephane Nicoll * @see ConditionalOnExpression */ @Order(Ordered.LOWEST_PRECEDENCE - 20) @@ -43,19 +44,29 @@ class OnExpressionCondition extends SpringBootCondition { expression = wrapIfNecessary(expression); String rawExpression = expression; expression = context.getEnvironment().resolvePlaceholders(expression); + ConditionMessage.Builder messageBuilder = ConditionMessage + .forCondition(ConditionalOnExpression.class, "(" + rawExpression + ")"); ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); - BeanExpressionResolver resolver = (beanFactory != null - ? beanFactory.getBeanExpressionResolver() : null); - BeanExpressionContext expressionContext = (beanFactory != null - ? new BeanExpressionContext(beanFactory, null) : null); + if (beanFactory != null) { + boolean result = evaluateExpression(beanFactory, expression); + return new ConditionOutcome(result, messageBuilder.resultedIn(result)); + } + else { + return ConditionOutcome + .noMatch(messageBuilder.because("no BeanFactory available.")); + } + } + + private Boolean evaluateExpression(ConfigurableListableBeanFactory beanFactory, + String expression) { + BeanExpressionResolver resolver = beanFactory.getBeanExpressionResolver(); if (resolver == null) { resolver = new StandardBeanExpressionResolver(); } + BeanExpressionContext expressionContext = new BeanExpressionContext(beanFactory, + null); Object result = resolver.evaluate(expression, expressionContext); - boolean match = result != null && (boolean) result; - return new ConditionOutcome(match, ConditionMessage - .forCondition(ConditionalOnExpression.class, "(" + rawExpression + ")") - .resultedIn(result)); + return (result != null && (boolean) result); } /** diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnExpressionTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnExpressionTests.java index c855110adf..ac24a5675f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnExpressionTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnExpressionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -16,13 +16,21 @@ package org.springframework.boot.autoconfigure.condition; +import java.util.HashMap; +import java.util.Map; + import org.junit.Test; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Configuration; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; /** * Tests for {@link ConditionalOnExpression}. @@ -41,17 +49,39 @@ public class ConditionalOnExpressionTests { } @Test - public void expressionIsFalse() { + public void expressionEvaluatesToTrueRegisterBean() { this.contextRunner.withUserConfiguration(MissingConfiguration.class) .run((context) -> assertThat(context).doesNotHaveBean("foo")); } @Test - public void expressionIsNull() { + public void expressionEvaluatesToFalseDoesNotRegisterBean() { this.contextRunner.withUserConfiguration(NullConfiguration.class) .run((context) -> assertThat(context).doesNotHaveBean("foo")); } + @Test + public void expressionEvaluationWithNoBeanFactoryDoesNotMatch() { + OnExpressionCondition condition = new OnExpressionCondition(); + MockEnvironment environment = new MockEnvironment(); + ConditionContext conditionContext = mock(ConditionContext.class); + given(conditionContext.getEnvironment()).willReturn(environment); + ConditionOutcome outcome = condition.getMatchOutcome(conditionContext, + mockMetaData("invalid-spel")); + assertThat(outcome.isMatch()).isFalse(); + assertThat(outcome.getMessage()).contains("invalid-spel") + .contains("no BeanFactory available"); + } + + private AnnotatedTypeMetadata mockMetaData(String value) { + AnnotatedTypeMetadata metadata = mock(AnnotatedTypeMetadata.class); + Map attributes = new HashMap<>(); + attributes.put("value", value); + given(metadata.getAnnotationAttributes(ConditionalOnExpression.class.getName())) + .willReturn(attributes); + return metadata; + } + @Configuration @ConditionalOnExpression("false") protected static class MissingConfiguration {