Browse Source
Merge OnMissingBeanCondition into OnBeanCondition and simplify code. Polish on bean conditionspull/23/head
6 changed files with 203 additions and 235 deletions
@ -1,184 +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 java.lang.reflect.Method; |
|
||||||
import java.util.ArrayList; |
|
||||||
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; |
|
||||||
import org.springframework.context.annotation.Bean; |
|
||||||
import org.springframework.context.annotation.ConditionContext; |
|
||||||
import org.springframework.context.annotation.ConfigurationCondition; |
|
||||||
import org.springframework.core.type.AnnotatedTypeMetadata; |
|
||||||
import org.springframework.core.type.MethodMetadata; |
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.util.ClassUtils; |
|
||||||
import org.springframework.util.MultiValueMap; |
|
||||||
import org.springframework.util.ReflectionUtils; |
|
||||||
import org.springframework.util.ReflectionUtils.MethodCallback; |
|
||||||
|
|
||||||
/** |
|
||||||
* Base for {@link OnBeanCondition} and {@link OnMissingBeanCondition}. |
|
||||||
* |
|
||||||
* @author Phillip Webb |
|
||||||
* @author Dave Syer |
|
||||||
*/ |
|
||||||
abstract class AbstractOnBeanCondition implements ConfigurationCondition { |
|
||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass()); |
|
||||||
|
|
||||||
protected abstract Class<?> annotationClass(); |
|
||||||
|
|
||||||
@Override |
|
||||||
public ConfigurationPhase getConfigurationPhase() { |
|
||||||
return ConfigurationPhase.REGISTER_BEAN; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { |
|
||||||
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes( |
|
||||||
annotationClass().getName(), true); |
|
||||||
final List<String> beanClasses = collect(attributes, "value"); |
|
||||||
final List<String> beanNames = collect(attributes, "name"); |
|
||||||
|
|
||||||
if (beanClasses.size() == 0) { |
|
||||||
if (metadata instanceof MethodMetadata |
|
||||||
&& metadata.isAnnotated(Bean.class.getName())) { |
|
||||||
try { |
|
||||||
final MethodMetadata methodMetadata = (MethodMetadata) metadata; |
|
||||||
// We should be safe to load at this point since we are in the
|
|
||||||
// REGISTER_BEAN phase
|
|
||||||
Class<?> configClass = ClassUtils.forName( |
|
||||||
methodMetadata.getDeclaringClassName(), |
|
||||||
context.getClassLoader()); |
|
||||||
ReflectionUtils.doWithMethods(configClass, new MethodCallback() { |
|
||||||
@Override |
|
||||||
public void doWith(Method method) |
|
||||||
throws IllegalArgumentException, IllegalAccessException { |
|
||||||
if (methodMetadata.getMethodName().equals(method.getName())) { |
|
||||||
beanClasses.add(method.getReturnType().getName()); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
catch (Exception ex) { |
|
||||||
// swallow exception and continue
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Assert.isTrue(beanClasses.size() > 0 || beanNames.size() > 0, |
|
||||||
"@" + ClassUtils.getShortName(annotationClass()) |
|
||||||
+ " annotations must specify at least one bean"); |
|
||||||
|
|
||||||
return matches(context, metadata, beanClasses, beanNames); |
|
||||||
} |
|
||||||
|
|
||||||
protected boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata, |
|
||||||
List<String> beanClasses, List<String> beanNames) throws LinkageError { |
|
||||||
|
|
||||||
String checking = ConditionLogUtils.getPrefix(this.logger, metadata); |
|
||||||
|
|
||||||
SearchStrategy search = (SearchStrategy) metadata.getAnnotationAttributes( |
|
||||||
annotationClass().getName()).get("search"); |
|
||||||
search = search == null ? SearchStrategy.ALL : search; |
|
||||||
|
|
||||||
boolean considerHierarchy = search == SearchStrategy.ALL; |
|
||||||
boolean parentOnly = search == SearchStrategy.PARENTS; |
|
||||||
|
|
||||||
List<String> beanClassesFound = new ArrayList<String>(); |
|
||||||
List<String> beanNamesFound = new ArrayList<String>(); |
|
||||||
|
|
||||||
// eagerInit set to false to prevent early instantiation (some
|
|
||||||
// factory beans will not be able to determine their object type at this
|
|
||||||
// stage, so those are not eligible for matching this condition)
|
|
||||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); |
|
||||||
if (parentOnly) { |
|
||||||
BeanFactory parent = beanFactory.getParentBeanFactory(); |
|
||||||
if (!(parent instanceof ConfigurableListableBeanFactory)) { |
|
||||||
throw new IllegalStateException( |
|
||||||
"Cannot use parentOnly if parent is not ConfigurableListableBeanFactory"); |
|
||||||
} |
|
||||||
beanFactory = (ConfigurableListableBeanFactory) parent; |
|
||||||
} |
|
||||||
for (String beanClass : beanClasses) { |
|
||||||
try { |
|
||||||
Class<?> type = ClassUtils.forName(beanClass, context.getClassLoader()); |
|
||||||
String[] beans = (considerHierarchy ? BeanFactoryUtils |
|
||||||
.beanNamesForTypeIncludingAncestors(beanFactory, type, false, |
|
||||||
false) : beanFactory.getBeanNamesForType(type, false, |
|
||||||
false)); |
|
||||||
if (beans.length != 0) { |
|
||||||
beanClassesFound.add(beanClass); |
|
||||||
} |
|
||||||
} |
|
||||||
catch (ClassNotFoundException ex) { |
|
||||||
// swallow exception and continue
|
|
||||||
} |
|
||||||
} |
|
||||||
for (String beanName : beanNames) { |
|
||||||
if (considerHierarchy ? beanFactory.containsBean(beanName) : beanFactory |
|
||||||
.containsLocalBean(beanName)) { |
|
||||||
beanNamesFound.add(beanName); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
boolean result = evaluate(beanClassesFound, beanNamesFound); |
|
||||||
if (this.logger.isDebugEnabled()) { |
|
||||||
logFoundResults(checking, "class", beanClasses, beanClassesFound); |
|
||||||
logFoundResults(checking, "name", beanNames, beanClassesFound); |
|
||||||
this.logger.debug(checking + "Match result is: " + result); |
|
||||||
} |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
private void logFoundResults(String prefix, String type, List<?> candidates, |
|
||||||
List<?> found) { |
|
||||||
if (!candidates.isEmpty()) { |
|
||||||
this.logger.debug(prefix + "Looking for beans with " + type + ": " |
|
||||||
+ candidates); |
|
||||||
if (found.isEmpty()) { |
|
||||||
this.logger.debug(prefix + "Found no beans"); |
|
||||||
} |
|
||||||
else { |
|
||||||
this.logger.debug(prefix + "Found beans with " + type + ": " + found); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected boolean evaluate(List<String> beanClassesFound, List<String> beanNamesFound) { |
|
||||||
return !beanClassesFound.isEmpty() || !beanNamesFound.isEmpty(); |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" }) |
|
||||||
private List<String> collect(MultiValueMap<String, Object> attributes, String key) { |
|
||||||
List<String> collected = new ArrayList<String>(); |
|
||||||
List<String[]> valueList = (List) attributes.get(key); |
|
||||||
for (String[] valueArray : valueList) { |
|
||||||
for (String value : valueArray) { |
|
||||||
collected.add(value); |
|
||||||
} |
|
||||||
} |
|
||||||
return collected; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,40 +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 java.util.List; |
|
||||||
|
|
||||||
import org.springframework.context.annotation.Condition; |
|
||||||
|
|
||||||
/** |
|
||||||
* {@link Condition} that checks that specific beans are missing. |
|
||||||
* |
|
||||||
* @author Phillip Webb |
|
||||||
* @see ConditionalOnMissingBean |
|
||||||
*/ |
|
||||||
class OnMissingBeanCondition extends AbstractOnBeanCondition { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Class<?> annotationClass() { |
|
||||||
return ConditionalOnMissingBean.class; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected boolean evaluate(List<String> beanClassesFound, List<String> beanNamesFound) { |
|
||||||
return !super.evaluate(beanClassesFound, beanNamesFound); |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue