Avoid defensive checks against Java 8 API (java.util.Optional etc)

This commit also fixes broken javadoc links and code references.

Issue: SPR-13188
This commit is contained in:
Juergen Hoeller
2016-07-05 02:08:59 +02:00
parent adb935db79
commit 51252ebbca
98 changed files with 290 additions and 1232 deletions

View File

@@ -38,9 +38,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.UsesJava8;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -75,19 +73,6 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
*/
private static final Log logger = LogFactory.getLog(AbstractNestablePropertyAccessor.class);
private static Class<?> javaUtilOptionalClass = null;
static {
try {
javaUtilOptionalClass =
ClassUtils.forName("java.util.Optional", AbstractNestablePropertyAccessor.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// Java 8 not available - Optional references simply not supported then.
}
}
private int autoGrowCollectionLimit = Integer.MAX_VALUE;
Object wrappedObject;
@@ -202,13 +187,8 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
* @param rootObject the root object at the top of the path
*/
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
Assert.notNull(object, "Target object must not be null");
if (object.getClass() == javaUtilOptionalClass) {
this.wrappedObject = OptionalUnwrapper.unwrap(object);
}
else {
this.wrappedObject = object;
}
this.wrappedObject = ObjectUtils.unwrapOptional(object);
Assert.notNull(this.wrappedObject, "Target object must not be null");
this.nestedPath = (nestedPath != null ? nestedPath : "");
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : this.wrappedObject);
this.nestedPropertyAccessors = null;
@@ -834,7 +814,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
PropertyTokenHolder tokens = getPropertyNameTokens(nestedProperty);
String canonicalName = tokens.canonicalName;
Object value = getPropertyValue(tokens);
if (value == null || (value.getClass() == javaUtilOptionalClass && OptionalUnwrapper.isEmpty(value))) {
if (value == null || (value instanceof Optional && !((Optional) value).isPresent())) {
if (isAutoGrowNestedPaths()) {
value = setDefaultValue(tokens);
}
@@ -845,8 +825,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
// Lookup cached sub-PropertyAccessor, create new one if not found.
AbstractNestablePropertyAccessor nestedPa = this.nestedPropertyAccessors.get(canonicalName);
if (nestedPa == null || nestedPa.getWrappedInstance() !=
(value.getClass() == javaUtilOptionalClass ? OptionalUnwrapper.unwrap(value) : value)) {
if (nestedPa == null || nestedPa.getWrappedInstance() != ObjectUtils.unwrapOptional(value)) {
if (logger.isTraceEnabled()) {
logger.trace("Creating new nested " + getClass().getSimpleName() + " for property '" + canonicalName + "'");
}
@@ -1037,24 +1016,4 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
public String[] keys;
}
/**
* Inner class to avoid a hard dependency on Java 8.
*/
@UsesJava8
private static class OptionalUnwrapper {
public static Object unwrap(Object optionalObject) {
Optional<?> optional = (Optional<?>) optionalObject;
Assert.isTrue(optional.isPresent(), "Optional value must be present");
Object result = optional.get();
Assert.isTrue(!(result instanceof Optional), "Multi-level Optional usage not supported");
return result;
}
public static boolean isEmpty(Object optionalObject) {
return !((Optional<?>) optionalObject).isPresent();
}
}
}

View File

@@ -24,6 +24,7 @@ import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -54,20 +55,6 @@ class TypeConverterDelegate {
private static final Log logger = LogFactory.getLog(TypeConverterDelegate.class);
/** Java 8's java.util.Optional.empty() instance */
private static Object javaUtilOptionalEmpty = null;
static {
try {
Class<?> clazz = ClassUtils.forName("java.util.Optional", TypeConverterDelegate.class.getClassLoader());
javaUtilOptionalEmpty = ClassUtils.getMethod(clazz, "empty").invoke(null);
}
catch (Exception ex) {
// Java 8 not available - conversion to Optional not supported then.
}
}
private final PropertyEditorRegistrySupport propertyEditorRegistry;
private final Object targetObject;
@@ -269,8 +256,8 @@ class TypeConverterDelegate {
}
else {
// convertedValue == null
if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
convertedValue = javaUtilOptionalEmpty;
if (requiredType == Optional.class) {
convertedValue = Optional.empty();
}
}

View File

@@ -69,7 +69,6 @@ import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.core.OrderComparator;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.UsesJava8;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CompositeIterator;
@@ -114,18 +113,9 @@ import org.springframework.util.StringUtils;
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private static Class<?> javaUtilOptionalClass = null;
private static Class<?> javaxInjectProviderClass = null;
static {
try {
javaUtilOptionalClass =
ClassUtils.forName("java.util.Optional", DefaultListableBeanFactory.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// Java 8 not available - Optional references simply not supported then.
}
try {
javaxInjectProviderClass =
ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
@@ -1002,8 +992,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {
return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);
if (descriptor.getDependencyType() == Optional.class) {
return createOptionalDependency(descriptor, beanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
@@ -1403,6 +1393,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
"Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
}
private Optional<?> createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
@Override
public boolean isRequired() {
return false;
}
@Override
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
super.resolveCandidate(beanName, beanFactory));
}
};
descriptorToUse.increaseNestingLevel();
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
}
@Override
public String toString() {
@@ -1466,30 +1473,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
/**
* Separate inner class for avoiding a hard dependency on the {@code javax.inject} API.
*/
@UsesJava8
private class OptionalDependencyFactory {
public Object createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
@Override
public boolean isRequired() {
return false;
}
@Override
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
super.resolveCandidate(beanName, beanFactory));
}
};
descriptorToUse.increaseNestingLevel();
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
}
}
/**
* Serializable ObjectFactory/ObjectProvider for lazy resolution of a dependency.
*/
@@ -1504,14 +1487,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
public DependencyObjectProvider(DependencyDescriptor descriptor, String beanName) {
this.descriptor = new DependencyDescriptor(descriptor);
this.descriptor.increaseNestingLevel();
this.optional = this.descriptor.getDependencyType().equals(javaUtilOptionalClass);
this.optional = (this.descriptor.getDependencyType() == Optional.class);
this.beanName = beanName;
}
@Override
public Object getObject() throws BeansException {
if (this.optional) {
return new OptionalDependencyFactory().createOptionalDependency(this.descriptor, this.beanName);
return createOptionalDependency(this.descriptor, this.beanName);
}
else {
return doResolveDependency(this.descriptor, this.beanName, null, null);
@@ -1521,7 +1504,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public Object getObject(final Object... args) throws BeansException {
if (this.optional) {
return new OptionalDependencyFactory().createOptionalDependency(this.descriptor, this.beanName, args);
return createOptionalDependency(this.descriptor, this.beanName, args);
}
else {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
@@ -1537,7 +1520,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public Object getIfAvailable() throws BeansException {
if (this.optional) {
return new OptionalDependencyFactory().createOptionalDependency(this.descriptor, this.beanName);
return createOptionalDependency(this.descriptor, this.beanName);
}
else {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
@@ -1563,7 +1546,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
};
if (this.optional) {
return new OptionalDependencyFactory().createOptionalDependency(descriptorToUse, this.beanName);
return createOptionalDependency(descriptorToUse, this.beanName);
}
else {
return doResolveDependency(descriptorToUse, this.beanName, null, null);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -19,8 +19,6 @@ package org.springframework.beans.propertyeditors;
import java.beans.PropertyEditorSupport;
import java.time.ZoneId;
import org.springframework.lang.UsesJava8;
/**
* Editor for {@code java.time.ZoneId}, translating zone ID Strings into {@code ZoneId}
* objects. Exposes the {@code TimeZone} ID as a text representation.
@@ -30,7 +28,6 @@ import org.springframework.lang.UsesJava8;
* @see java.time.ZoneId
* @see TimeZoneEditor
*/
@UsesJava8
public class ZoneIdEditor extends PropertyEditorSupport {
@Override