From 4298744c4ab35b75869470c1eb7e63ab87286dca Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 3 Jul 2018 17:06:35 +0200 Subject: [PATCH] Polishing --- .../support/DefaultListableBeanFactory.java | 48 +++++++++---------- .../core/GenericTypeResolver.java | 4 +- .../core/SerializableTypeWrapper.java | 23 ++++----- .../org/springframework/http/HttpHeaders.java | 22 ++++----- .../AbstractHttpMessageConverter.java | 6 ++- .../AbstractJaxb2HttpMessageConverter.java | 6 +-- .../xml/AbstractXmlHttpMessageConverter.java | 21 ++++---- .../Jaxb2CollectionHttpMessageConverter.java | 6 +-- .../Jaxb2RootElementHttpMessageConverter.java | 7 ++- 9 files changed, 75 insertions(+), 68 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 58ee2b2ddd..0101742e66 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -80,7 +80,7 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** - * Default implementation of the + * Spring's default implementation of the * {@link org.springframework.beans.factory.ListableBeanFactory} and * {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory * based on bean definition objects. @@ -444,9 +444,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto if (allowEagerInit) { throw ex; } - // Probably contains a placeholder: let's ignore it for type matching purposes. - if (this.logger.isDebugEnabled()) { - this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex); + // Probably a class name with a placeholder: let's ignore it for type matching purposes. + if (logger.isDebugEnabled()) { + logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex); } onSuppressedException(ex); } @@ -454,9 +454,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto if (allowEagerInit) { throw ex; } - // Probably contains a placeholder: let's ignore it for type matching purposes. - if (this.logger.isDebugEnabled()) { - this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex); + // Probably some metadata with a placeholder: let's ignore it for type matching purposes. + if (logger.isDebugEnabled()) { + logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex); } onSuppressedException(ex); } @@ -523,8 +523,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (isCurrentlyInCreation(bce.getBeanName())) { - if (this.logger.isDebugEnabled()) { - this.logger.debug("Ignoring match to currently created bean '" + beanName + "': " + + if (logger.isDebugEnabled()) { + logger.debug("Ignoring match to currently created bean '" + beanName + "': " + ex.getMessage()); } onSuppressedException(ex); @@ -681,8 +681,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { BeanDefinition bd = this.beanDefinitionMap.get(beanName); if (bd == null) { - if (this.logger.isTraceEnabled()) { - this.logger.trace("No bean named '" + beanName + "' found in " + this); + if (logger.isTraceEnabled()) { + logger.trace("No bean named '" + beanName + "' found in " + this); } throw new NoSuchBeanDefinitionException(beanName); } @@ -726,8 +726,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @Override public void preInstantiateSingletons() throws BeansException { - if (this.logger.isDebugEnabled()) { - this.logger.debug("Pre-instantiating singletons in " + this); + if (logger.isDebugEnabled()) { + logger.debug("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. @@ -817,22 +817,22 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE - if (this.logger.isWarnEnabled()) { - this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + + if (logger.isWarnEnabled()) { + logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(oldBeanDefinition)) { - if (this.logger.isInfoEnabled()) { - this.logger.info("Overriding bean definition for bean '" + beanName + + if (logger.isInfoEnabled()) { + logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else { - if (this.logger.isDebugEnabled()) { - this.logger.debug("Overriding bean definition for bean '" + beanName + + if (logger.isDebugEnabled()) { + logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } @@ -875,8 +875,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto BeanDefinition bd = this.beanDefinitionMap.remove(beanName); if (bd == null) { - if (this.logger.isTraceEnabled()) { - this.logger.trace("No bean named '" + beanName + "' found in " + this); + if (logger.isTraceEnabled()) { + logger.trace("No bean named '" + beanName + "' found in " + this); } throw new NoSuchBeanDefinitionException(beanName); } @@ -1637,7 +1637,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto return new OptionalDependencyFactory().createOptionalDependency(this.descriptor, this.beanName, args); } else { - DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) { + DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) { @Override public Object resolveCandidate(String beanName, Class requiredType, BeanFactory beanFactory) { return ((AbstractBeanFactory) beanFactory).getBean(beanName, requiredType, args); @@ -1653,7 +1653,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto return new OptionalDependencyFactory().createOptionalDependency(this.descriptor, this.beanName); } else { - DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) { + DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) { @Override public boolean isRequired() { return false; @@ -1665,7 +1665,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @Override public Object getIfUnique() throws BeansException { - DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) { + DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) { @Override public boolean isRequired() { return false; diff --git a/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java b/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java index ee35af14aa..c37571c4f9 100644 --- a/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java +++ b/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-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. @@ -198,7 +198,7 @@ public abstract class GenericTypeResolver { * if not resolvable or if the single argument is of type {@link WildcardType}. */ public static Class resolveReturnTypeArgument(Method method, Class genericIfc) { - Assert.notNull(method, "method must not be null"); + Assert.notNull(method, "Method must not be null"); ResolvableType resolvableType = ResolvableType.forMethodReturnType(method).as(genericIfc); if (!resolvableType.hasGenerics() || resolvableType.getType() instanceof WildcardType) { return null; diff --git a/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java b/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java index 647cb5bd2d..894c0bf939 100644 --- a/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java +++ b/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-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. @@ -30,7 +30,6 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; -import org.springframework.util.Assert; import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.ReflectionUtils; @@ -66,7 +65,6 @@ abstract class SerializableTypeWrapper { * Return a {@link Serializable} variant of {@link Field#getGenericType()}. */ public static Type forField(Field field) { - Assert.notNull(field, "Field must not be null"); return forTypeProvider(new FieldTypeProvider(field)); } @@ -144,26 +142,29 @@ abstract class SerializableTypeWrapper { /** * Return a {@link Serializable} {@link Type} backed by a {@link TypeProvider} . */ - static Type forTypeProvider(final TypeProvider provider) { - Assert.notNull(provider, "Provider must not be null"); - if (provider.getType() instanceof Serializable || provider.getType() == null) { - return provider.getType(); + static Type forTypeProvider(TypeProvider provider) { + Type providedType = provider.getType(); + if (providedType == null || providedType instanceof Serializable) { + // No serializable type wrapping necessary (e.g. for java.lang.Class) + return providedType; } - Type cached = cache.get(provider.getType()); + + // Obtain a serializable type proxy for the given provider... + Type cached = cache.get(providedType); if (cached != null) { return cached; } for (Class type : SUPPORTED_SERIALIZABLE_TYPES) { - if (type.isAssignableFrom(provider.getType().getClass())) { + if (type.isInstance(providedType)) { ClassLoader classLoader = provider.getClass().getClassLoader(); Class[] interfaces = new Class[] {type, SerializableTypeProxy.class, Serializable.class}; InvocationHandler handler = new TypeProxyInvocationHandler(provider); cached = (Type) Proxy.newProxyInstance(classLoader, interfaces, handler); - cache.put(provider.getType(), cached); + cache.put(providedType, cached); return cached; } } - throw new IllegalArgumentException("Unsupported Type class: " + provider.getType().getClass().getName()); + throw new IllegalArgumentException("Unsupported Type class: " + providedType.getClass().getName()); } diff --git a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java index 517c67e00c..bca45349b5 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java +++ b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java @@ -162,7 +162,7 @@ public class HttpHeaders implements MultiValueMap, Serializable */ public static final String CONTENT_ENCODING = "Content-Encoding"; /** - * The HTTP {@code Content-Disposition} header field name + * The HTTP {@code Content-Disposition} header field name. * @see RFC 6266 */ public static final String CONTENT_DISPOSITION = "Content-Disposition"; @@ -368,7 +368,15 @@ public class HttpHeaders implements MultiValueMap, Serializable public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; /** - * Date formats as specified in the HTTP RFC + * Pattern matching ETag multiple field values in headers such as "If-Match", "If-None-Match". + * @see Section 2.3 of RFC 7232 + */ + private static final Pattern ETAG_HEADER_VALUE_PATTERN = Pattern.compile("\\*|\\s*((W\\/)?(\"[^\"]*\"))\\s*,?"); + + private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); + + /** + * Date formats as specified in the HTTP RFC. * @see Section 7.1.1.1 of RFC 7231 */ private static final String[] DATE_FORMATS = new String[] { @@ -377,14 +385,6 @@ public class HttpHeaders implements MultiValueMap, Serializable "EEE MMM dd HH:mm:ss yyyy" }; - /** - * Pattern matching ETag multiple field values in headers such as "If-Match", "If-None-Match" - * @see Section 2.3 of RFC 7232 - */ - private static final Pattern ETAG_HEADER_VALUE_PATTERN = Pattern.compile("\\*|\\s*((W\\/)?(\"[^\"]*\"))\\s*,?"); - - private static TimeZone GMT = TimeZone.getTimeZone("GMT"); - private final Map> headers; @@ -1052,7 +1052,7 @@ public class HttpHeaders implements MultiValueMap, Serializable * {@link IllegalArgumentException} ({@code true}) or rather return -1 * in that case ({@code false}) * @return the parsed date header, or -1 if none (or invalid) - */ + */ private long getFirstDate(String headerName, boolean rejectInvalid) { String headerValue = getFirst(headerName); if (headerValue == null) { diff --git a/spring-web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java index 88019fc56c..08e64b8228 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java @@ -189,7 +189,9 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv * Future implementations might add some default behavior, however. */ @Override - public final T read(Class clazz, HttpInputMessage inputMessage) throws IOException { + public final T read(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + return readInternal(clazz, inputMessage); } @@ -235,7 +237,7 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv * {@link #getContentLength}, and sets the corresponding headers. * @since 4.2 */ - protected void addDefaultHeaders(HttpHeaders headers, T t, MediaType contentType) throws IOException{ + protected void addDefaultHeaders(HttpHeaders headers, T t, MediaType contentType) throws IOException { if (headers.getContentType() == null) { MediaType contentTypeToUse = contentType; if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) { diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java index 71af0810fd..11b42b6407 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-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. @@ -74,7 +74,7 @@ public abstract class AbstractJaxb2HttpMessageConverter extends AbstractXmlHt * @return the {@code Unmarshaller} * @throws HttpMessageConversionException in case of JAXB errors */ - protected final Unmarshaller createUnmarshaller(Class clazz) throws JAXBException { + protected final Unmarshaller createUnmarshaller(Class clazz) { try { JAXBContext jaxbContext = getJaxbContext(clazz); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); @@ -104,7 +104,7 @@ public abstract class AbstractJaxb2HttpMessageConverter extends AbstractXmlHt * @throws HttpMessageConversionException in case of JAXB errors */ protected final JAXBContext getJaxbContext(Class clazz) { - Assert.notNull(clazz, "'clazz' must not be null"); + Assert.notNull(clazz, "Class must not be null"); JAXBContext jaxbContext = this.jaxbContexts.get(clazz); if (jaxbContext == null) { try { diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java index f10f7114eb..78e7ecca76 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-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,7 +29,8 @@ import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.AbstractHttpMessageConverter; -import org.springframework.http.converter.HttpMessageConversionException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; /** * Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters} @@ -57,12 +58,16 @@ public abstract class AbstractXmlHttpMessageConverter extends AbstractHttpMes @Override - public final T readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { + public final T readInternal(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputMessage.getBody())); } @Override - protected final void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException { + protected final void writeInternal(T t, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + writeToResult(t, outputMessage.getHeaders(), new StreamResult(outputMessage.getBody())); } @@ -84,10 +89,10 @@ public abstract class AbstractXmlHttpMessageConverter extends AbstractHttpMes * @param source the HTTP input body * @return the converted object * @throws IOException in case of I/O errors - * @throws org.springframework.http.converter.HttpMessageConversionException in case of conversion errors + * @throws HttpMessageNotReadableException in case of conversion errors */ protected abstract T readFromSource(Class clazz, HttpHeaders headers, Source source) - throws IOException; + throws IOException, HttpMessageNotReadableException; /** * Abstract template method called from {@link #writeInternal(Object, HttpOutputMessage)}. @@ -95,9 +100,9 @@ public abstract class AbstractXmlHttpMessageConverter extends AbstractHttpMes * @param headers the HTTP output headers * @param result the HTTP output body * @throws IOException in case of I/O errors - * @throws HttpMessageConversionException in case of conversion errors + * @throws HttpMessageNotWritableException in case of conversion errors */ protected abstract void writeToResult(T t, HttpHeaders headers, Result result) - throws IOException; + throws IOException, HttpMessageNotWritableException; } diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java index 240062ad6b..642159c05f 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java @@ -1,11 +1,11 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -169,7 +169,7 @@ public class Jaxb2CollectionHttpMessageConverter "Could not unmarshal to [" + elementClass + "]: " + ex.getMessage(), ex); } catch (JAXBException ex) { - throw new HttpMessageConversionException("Could not instantiate JAXBContext: " + ex.getMessage(), ex); + throw new HttpMessageConversionException("Invalid JAXB setup: " + ex.getMessage(), ex); } catch (XMLStreamException ex) { throw new HttpMessageConversionException(ex.getMessage(), ex); diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java index fe5f780ab0..41f01a95e6 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-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. @@ -146,10 +146,9 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa } catch (UnmarshalException ex) { throw new HttpMessageNotReadableException("Could not unmarshal to [" + clazz + "]: " + ex.getMessage(), ex); - } catch (JAXBException ex) { - throw new HttpMessageConversionException("Could not instantiate JAXBContext: " + ex.getMessage(), ex); + throw new HttpMessageConversionException("Invalid JAXB setup: " + ex.getMessage(), ex); } } @@ -189,7 +188,7 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa throw new HttpMessageNotWritableException("Could not marshal [" + o + "]: " + ex.getMessage(), ex); } catch (JAXBException ex) { - throw new HttpMessageConversionException("Could not instantiate JAXBContext: " + ex.getMessage(), ex); + throw new HttpMessageConversionException("Invalid JAXB setup: " + ex.getMessage(), ex); } }