Polishing

This commit is contained in:
Juergen Hoeller 2014-07-29 11:42:37 +02:00
parent 7bc966032b
commit 8f484d382e
14 changed files with 220 additions and 224 deletions

View File

@ -40,8 +40,7 @@ class TestSourceSetDependenciesPlugin implements Plugin<Project> {
} }
} }
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies, private void collectProjectDependencies(Set<ProjectDependency> projectDependencies, Project project) {
Project project) {
for (def configurationName in ["compile", "optional", "provided", "testCompile"]) { for (def configurationName in ["compile", "optional", "provided", "testCompile"]) {
Configuration configuration = project.getConfigurations().findByName(configurationName) Configuration configuration = project.getConfigurations().findByName(configurationName)
if (configuration) { if (configuration) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -27,20 +27,26 @@ import org.aspectj.lang.annotation.control.CodeGenerationHint;
* @since 2.5.2 * @since 2.5.2
*/ */
public abstract aspect AbstractDependencyInjectionAspect { public abstract aspect AbstractDependencyInjectionAspect {
/**
* Select construction join points for objects to inject dependencies private pointcut preConstructionCondition() :
*/ leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
public abstract pointcut beanConstruction(Object bean);
private pointcut postConstructionCondition() :
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
/** /**
* Select deserialization join points for objects to inject dependencies * Select least specific super type that is marked for DI
* (so that injection occurs only once with pre-construction injection).
*/ */
public abstract pointcut beanDeserialization(Object bean); public abstract pointcut leastSpecificSuperTypeConstruction();
/** /**
* Select join points in a configurable bean * Select the most-specific initialization join point
* (most concrete class) for the initialization of an instance.
*/ */
public abstract pointcut inConfigurableBean(); @CodeGenerationHint(ifNameSuffix="6f1")
public pointcut mostSpecificSubTypeConstruction() :
if (thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
/** /**
* Select join points in beans to be configured prior to construction? * Select join points in beans to be configured prior to construction?
@ -49,30 +55,21 @@ public abstract aspect AbstractDependencyInjectionAspect {
public pointcut preConstructionConfiguration() : if (false); public pointcut preConstructionConfiguration() : if (false);
/** /**
* Select the most-specific initialization join point * Select construction join points for objects to inject dependencies.
* (most concrete class) for the initialization of an instance.
*/ */
@CodeGenerationHint(ifNameSuffix="6f1") public abstract pointcut beanConstruction(Object bean);
public pointcut mostSpecificSubTypeConstruction() :
if (thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
/** /**
* Select least specific super type that is marked for DI (so that injection occurs only once with pre-construction inejection * Select deserialization join points for objects to inject dependencies.
*/ */
public abstract pointcut leastSpecificSuperTypeConstruction(); public abstract pointcut beanDeserialization(Object bean);
/** /**
* Configure the bean * Select join points in a configurable bean.
*/ */
public abstract void configureBean(Object bean); public abstract pointcut inConfigurableBean();
private pointcut preConstructionCondition() :
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
private pointcut postConstructionCondition() :
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
/** /**
* Pre-construction configuration. * Pre-construction configuration.
*/ */
@ -100,4 +97,10 @@ public abstract aspect AbstractDependencyInjectionAspect {
configureBean(bean); configureBean(bean);
} }
/**
* Configure the given bean.
*/
public abstract void configureBean(Object bean);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,49 +20,48 @@ import java.io.ObjectStreamException;
import java.io.Serializable; import java.io.Serializable;
/** /**
* An aspect that injects dependency into any object whose type implements the {@link ConfigurableObject} interface. * An aspect that injects dependency into any object whose type implements the
* <p> * {@link ConfigurableObject} interface.
* This aspect supports injecting into domain objects when they are created for the first time as well as *
* upon deserialization. Subaspects need to simply provide definition for the configureBean() method. This * <p>This aspect supports injecting into domain objects when they are created
* method may be implemented without relying on Spring container if so desired. * for the first time as well as upon deserialization. Subaspects need to simply
* </p> * provide definition for the configureBean() method. This method may be
* <p> * implemented without relying on Spring container if so desired.
* There are two cases that needs to be handled: *
* <p>There are two cases that needs to be handled:
* <ol> * <ol>
* <li>Normal object creation via the '{@code new}' operator: this is * <li>Normal object creation via the '{@code new}' operator: this is
* taken care of by advising {@code initialization()} join points.</li> * taken care of by advising {@code initialization()} join points.</li>
* <li>Object creation through deserialization: since no constructor is * <li>Object creation through deserialization: since no constructor is
* invoked during deserialization, the aspect needs to advise a method that a * invoked during deserialization, the aspect needs to advise a method that a
* deserialization mechanism is going to invoke. Ideally, we should not * deserialization mechanism is going to invoke. Ideally, we should not
* require user classes to implement any specific method. This implies that * require user classes to implement any specific method. This implies that
* we need to <i>introduce</i> the chosen method. We should also handle the cases * we need to <i>introduce</i> the chosen method. We should also handle the cases
* where the chosen method is already implemented in classes (in which case, * where the chosen method is already implemented in classes (in which case,
* the user's implementation for that method should take precedence over the * the user's implementation for that method should take precedence over the
* introduced implementation). There are a few choices for the chosen method: * introduced implementation). There are a few choices for the chosen method:
* <ul> * <ul>
* <li>readObject(ObjectOutputStream): Java requires that the method must be * <li>readObject(ObjectOutputStream): Java requires that the method must be
* {@code private}</p>. Since aspects cannot introduce a private member, * {@code private}</p>. Since aspects cannot introduce a private member,
* while preserving its name, this option is ruled out.</li> * while preserving its name, this option is ruled out.</li>
* <li>readResolve(): Java doesn't pose any restriction on an access specifier. * <li>readResolve(): Java doesn't pose any restriction on an access specifier.
* Problem solved! There is one (minor) limitation of this approach in * Problem solved! There is one (minor) limitation of this approach in
* that if a user class already has this method, that method must be * that if a user class already has this method, that method must be
* {@code public}. However, this shouldn't be a big burden, since * {@code public}. However, this shouldn't be a big burden, since
* use cases that need classes to implement readResolve() (custom enums, * use cases that need classes to implement readResolve() (custom enums,
* for example) are unlikely to be marked as &#64;Configurable, and * for example) are unlikely to be marked as &#64;Configurable, and
* in any case asking to make that method {@code public} should not * in any case asking to make that method {@code public} should not
* pose any undue burden.</li> * pose any undue burden.</li>
* </ul> * </ul>
* The minor collaboration needed by user classes (i.e., that the * The minor collaboration needed by user classes (i.e., that the implementation of
* implementation of {@code readResolve()}, if any, must be * {@code readResolve()}, if any, must be {@code public}) can be lifted as well if we
* {@code public}) can be lifted as well if we were to use an * were to use an experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
* experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
* </ol> * </ol>
*
* <p> * <p>While having type implement the {@link ConfigurableObject} interface is certainly
* While having type implement the {@link ConfigurableObject} interface is certainly a valid choice, an alternative * a valid choice, an alternative is to use a 'declare parents' statement another aspect
* is to use a 'declare parents' statement another aspect (a subaspect of this aspect would be a logical choice) * (a subaspect of this aspect would be a logical choice) that declares the classes that
* that declares the classes that need to be configured by supplying the {@link ConfigurableObject} interface. * need to be configured by supplying the {@link ConfigurableObject} interface.
* </p>
* *
* @author Ramnivas Laddad * @author Ramnivas Laddad
* @since 2.5.2 * @since 2.5.2
@ -72,35 +71,33 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
* Select initialization join point as object construction * Select initialization join point as object construction
*/ */
public pointcut beanConstruction(Object bean) : public pointcut beanConstruction(Object bean) :
initialization(ConfigurableObject+.new(..)) && this(bean); initialization(ConfigurableObject+.new(..)) && this(bean);
/** /**
* Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport * Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport
*/ */
public pointcut beanDeserialization(Object bean) : public pointcut beanDeserialization(Object bean) :
execution(Object ConfigurableDeserializationSupport+.readResolve()) && execution(Object ConfigurableDeserializationSupport+.readResolve()) && this(bean);
this(bean);
public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..)); public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..));
// Implementation to support re-injecting dependencies once an object is deserialized // Implementation to support re-injecting dependencies once an object is deserialized
/** /**
* Declare any class implementing Serializable and ConfigurableObject as also implementing * Declare any class implementing Serializable and ConfigurableObject as also implementing
* ConfigurableDeserializationSupport. This allows us to introduce the readResolve() * ConfigurableDeserializationSupport. This allows us to introduce the {@code readResolve()}
* method and select it with the beanDeserialization() pointcut. * method and select it with the beanDeserialization() pointcut.
*
* <p>Here is an improved version that uses the hasmethod() pointcut and lifts * <p>Here is an improved version that uses the hasmethod() pointcut and lifts
* even the minor requirement on user classes: * even the minor requirement on user classes:
* * <pre class="code">
* <pre class="code">declare parents: ConfigurableObject+ Serializable+ * declare parents: ConfigurableObject+ Serializable+
* && !hasmethod(Object readResolve() throws ObjectStreamException) * && !hasmethod(Object readResolve() throws ObjectStreamException)
* implements ConfigurableDeserializationSupport; * implements ConfigurableDeserializationSupport;
* </pre> * </pre>
*/ */
declare parents: declare parents: ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
/** /**
* A marker interface to which the {@code readResolve()} is introduced. * A marker interface to which the {@code readResolve()} is introduced.
@ -111,7 +108,6 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
/** /**
* Introduce the {@code readResolve()} method so that we can advise its * Introduce the {@code readResolve()} method so that we can advise its
* execution to configure the object. * execution to configure the object.
*
* <p>Note if a method with the same signature already exists in a * <p>Note if a method with the same signature already exists in a
* {@code Serializable} class of ConfigurableObject type, * {@code Serializable} class of ConfigurableObject type,
* that implementation will take precedence (a good thing, since we are * that implementation will take precedence (a good thing, since we are

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@ package org.springframework.beans.factory.aspectj;
import java.io.Serializable; import java.io.Serializable;
import org.aspectj.lang.annotation.control.CodeGenerationHint; import org.aspectj.lang.annotation.control.CodeGenerationHint;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
@ -44,48 +44,47 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
* @see org.springframework.beans.factory.annotation.Configurable * @see org.springframework.beans.factory.annotation.Configurable
* @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver * @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
*/ */
public aspect AnnotationBeanConfigurerAspect public aspect AnnotationBeanConfigurerAspect extends AbstractInterfaceDrivenDependencyInjectionAspect
extends AbstractInterfaceDrivenDependencyInjectionAspect
implements BeanFactoryAware, InitializingBean, DisposableBean { implements BeanFactoryAware, InitializingBean, DisposableBean {
private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport(); private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();
public pointcut inConfigurableBean() : @this(Configurable);
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*); public void setBeanFactory(BeanFactory beanFactory) {
this.beanConfigurerSupport.setBeanFactory(beanFactory);
declare parents: @Configurable * implements ConfigurableObject; this.beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
public void configureBean(Object bean) {
beanConfigurerSupport.configureBean(bean);
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
beanConfigurerSupport.setBeanFactory(beanFactory);
beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
} }
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
beanConfigurerSupport.afterPropertiesSet(); this.beanConfigurerSupport.afterPropertiesSet();
}
public void configureBean(Object bean) {
this.beanConfigurerSupport.configureBean(bean);
} }
public void destroy() throws Exception { public void destroy() throws Exception {
beanConfigurerSupport.destroy(); this.beanConfigurerSupport.destroy();
} }
public pointcut inConfigurableBean() : @this(Configurable);
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
/* /*
* An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object) * An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object)
*/ */
@CodeGenerationHint(ifNameSuffix="bb0") @CodeGenerationHint(ifNameSuffix="bb0")
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if (c.preConstruction()); private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if (c.preConstruction());
declare parents: @Configurable * implements ConfigurableObject;
/* /*
* This declaration shouldn't be needed, * This declaration shouldn't be needed,
* except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559) * except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
*/ */
declare parents: @Configurable Serializable+ declare parents: @Configurable Serializable+ implements ConfigurableDeserializationSupport;
implements ConfigurableDeserializationSupport;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -62,6 +62,7 @@ public final class Property {
private Annotation[] annotations; private Annotation[] annotations;
public Property(Class<?> objectType, Method readMethod, Method writeMethod) { public Property(Class<?> objectType, Method readMethod, Method writeMethod) {
this(objectType, readMethod, writeMethod, null); this(objectType, readMethod, writeMethod, null);
} }
@ -241,34 +242,25 @@ public final class Property {
} }
} }
@Override @Override
public int hashCode() { public boolean equals(Object other) {
final int prime = 31; if (this == other) {
int hashCode = 1; return true;
hashCode = prime * hashCode + ObjectUtils.nullSafeHashCode(this.objectType); }
hashCode = prime * hashCode + ObjectUtils.nullSafeHashCode(this.readMethod); if (!(other instanceof Property)) {
hashCode = prime * hashCode + ObjectUtils.nullSafeHashCode(this.writeMethod); return false;
hashCode = prime * hashCode + ObjectUtils.nullSafeHashCode(this.name); }
return hashCode; Property otherProperty = (Property) other;
return (ObjectUtils.nullSafeEquals(this.objectType, otherProperty.objectType) &&
ObjectUtils.nullSafeEquals(this.name, otherProperty.name) &&
ObjectUtils.nullSafeEquals(this.readMethod, otherProperty.readMethod) &&
ObjectUtils.nullSafeEquals(this.writeMethod, otherProperty.writeMethod));
} }
@Override @Override
public boolean equals(Object obj) { public int hashCode() {
if (this == obj) { return (ObjectUtils.nullSafeHashCode(this.objectType) * 31 + ObjectUtils.nullSafeHashCode(this.name));
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Property other = (Property) obj;
boolean equals = true;
equals &= ObjectUtils.nullSafeEquals(this.objectType, other.objectType);
equals &= ObjectUtils.nullSafeEquals(this.readMethod, other.readMethod);
equals &= ObjectUtils.nullSafeEquals(this.writeMethod, other.writeMethod);
equals &= ObjectUtils.nullSafeEquals(this.name, other.name);
return equals;
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -42,10 +42,12 @@ final class MapToMapConverter implements ConditionalGenericConverter {
private final ConversionService conversionService; private final ConversionService conversionService;
public MapToMapConverter(ConversionService conversionService) { public MapToMapConverter(ConversionService conversionService) {
this.conversionService = conversionService; this.conversionService = conversionService;
} }
@Override @Override
public Set<ConvertiblePair> getConvertibleTypes() { public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Map.class, Map.class)); return Collections.singleton(new ConvertiblePair(Map.class, Map.class));
@ -88,6 +90,7 @@ final class MapToMapConverter implements ConditionalGenericConverter {
return targetMap; return targetMap;
} }
// internal helpers // internal helpers
private boolean canConvertKey(TypeDescriptor sourceType, TypeDescriptor targetType) { private boolean canConvertKey(TypeDescriptor sourceType, TypeDescriptor targetType) {
@ -114,10 +117,12 @@ final class MapToMapConverter implements ConditionalGenericConverter {
return this.conversionService.convert(sourceValue, sourceType.getMapValueTypeDescriptor(sourceValue), targetType); return this.conversionService.convert(sourceValue, sourceType.getMapValueTypeDescriptor(sourceValue), targetType);
} }
private static class MapEntry { private static class MapEntry {
private Object key; private final Object key;
private Object value;
private final Object value;
public MapEntry(Object key, Object value) { public MapEntry(Object key, Object value) {
this.key = key; this.key = key;
@ -125,7 +130,7 @@ final class MapToMapConverter implements ConditionalGenericConverter {
} }
public void addToMap(Map<Object, Object> map) { public void addToMap(Map<Object, Object> map) {
map.put(key, value); map.put(this.key, this.value);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,23 +31,22 @@ import org.springframework.util.Assert;
* is required. * is required.
* *
* @author Phillip Webb * @author Phillip Webb
* @param <T> The type of objects being compared
* @see CompoundComparator
* @since 3.2 * @since 3.2
* @param <T> the type of objects being compared
* @see CompoundComparator
*/ */
public class InstanceComparator<T> implements Comparator<T> { public class InstanceComparator<T> implements Comparator<T> {
private Class<?>[] instanceOrder; private final Class<?>[] instanceOrder;
/** /**
* Create a new {@link InstanceComparator} instance. * Create a new {@link InstanceComparator} instance.
*
* @param instanceOrder the ordered list of classes that should be used when comparing * @param instanceOrder the ordered list of classes that should be used when comparing
* objects. Classes earlier in the list will be be given a higher priority. * objects. Classes earlier in the list will be be given a higher priority.
*/ */
public InstanceComparator(Class<?>... instanceOrder) { public InstanceComparator(Class<?>... instanceOrder) {
Assert.notNull(instanceOrder, "InstanceOrder must not be null"); Assert.notNull(instanceOrder, "'instanceOrder' must not be null");
this.instanceOrder = instanceOrder; this.instanceOrder = instanceOrder;
} }
@ -61,13 +60,13 @@ public class InstanceComparator<T> implements Comparator<T> {
private int getOrder(T object) { private int getOrder(T object) {
if (object != null) { if (object != null) {
for (int i = 0; i < instanceOrder.length; i++) { for (int i = 0; i < this.instanceOrder.length; i++) {
if (instanceOrder[i].isInstance(object)) { if (this.instanceOrder[i].isInstance(object)) {
return i; return i;
} }
} }
} }
return instanceOrder.length; return this.instanceOrder.length;
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -73,26 +73,34 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
try { try {
setSupportsCatalogsInProcedureCalls(databaseMetaData.supportsCatalogsInProcedureCalls()); setSupportsCatalogsInProcedureCalls(databaseMetaData.supportsCatalogsInProcedureCalls());
} }
catch (SQLException se) { catch (SQLException ex) {
logger.warn("Error retrieving 'DatabaseMetaData.supportsCatalogsInProcedureCalls' - " + se.getMessage()); if (logger.isWarnEnabled()) {
logger.warn("Error retrieving 'DatabaseMetaData.supportsCatalogsInProcedureCalls' - " + ex.getMessage());
}
} }
try { try {
setSupportsSchemasInProcedureCalls(databaseMetaData.supportsSchemasInProcedureCalls()); setSupportsSchemasInProcedureCalls(databaseMetaData.supportsSchemasInProcedureCalls());
} }
catch (SQLException se) { catch (SQLException ex) {
logger.warn("Error retrieving 'DatabaseMetaData.supportsSchemasInProcedureCalls' - " + se.getMessage()); if (logger.isWarnEnabled()) {
logger.warn("Error retrieving 'DatabaseMetaData.supportsSchemasInProcedureCalls' - " + ex.getMessage());
}
} }
try { try {
setStoresUpperCaseIdentifiers(databaseMetaData.storesUpperCaseIdentifiers()); setStoresUpperCaseIdentifiers(databaseMetaData.storesUpperCaseIdentifiers());
} }
catch (SQLException se) { catch (SQLException ex) {
logger.warn("Error retrieving 'DatabaseMetaData.storesUpperCaseIdentifiers' - " + se.getMessage()); if (logger.isWarnEnabled()) {
logger.warn("Error retrieving 'DatabaseMetaData.storesUpperCaseIdentifiers' - " + ex.getMessage());
}
} }
try { try {
setStoresLowerCaseIdentifiers(databaseMetaData.storesLowerCaseIdentifiers()); setStoresLowerCaseIdentifiers(databaseMetaData.storesLowerCaseIdentifiers());
} }
catch (SQLException se) { catch (SQLException ex) {
logger.warn("Error retrieving 'DatabaseMetaData.storesLowerCaseIdentifiers' - " + se.getMessage()); if (logger.isWarnEnabled()) {
logger.warn("Error retrieving 'DatabaseMetaData.storesLowerCaseIdentifiers' - " + ex.getMessage());
}
} }
} }
@ -341,12 +349,8 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
columnType == DatabaseMetaData.procedureColumnInOut || columnType == DatabaseMetaData.procedureColumnInOut ||
columnType == DatabaseMetaData.procedureColumnOut)) { columnType == DatabaseMetaData.procedureColumnOut)) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Skipping metadata for: " logger.debug("Skipping metadata for: " + columnType + " " + procs.getInt("DATA_TYPE") +
+ columnName + " " + procs.getString("TYPE_NAME") + " " + procs.getBoolean("NULLABLE") +
" " + columnType +
" " + procs.getInt("DATA_TYPE") +
" " + procs.getString("TYPE_NAME") +
" " + procs.getBoolean("NULLABLE") +
" (probably a member of a collection)" " (probably a member of a collection)"
); );
} }
@ -355,18 +359,19 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
CallParameterMetaData meta = new CallParameterMetaData(columnName, columnType, CallParameterMetaData meta = new CallParameterMetaData(columnName, columnType,
procs.getInt("DATA_TYPE"), procs.getString("TYPE_NAME"), procs.getBoolean("NULLABLE") procs.getInt("DATA_TYPE"), procs.getString("TYPE_NAME"), procs.getBoolean("NULLABLE")
); );
callParameterMetaData.add(meta); this.callParameterMetaData.add(meta);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Retrieved metadata: " + meta.getParameterName() + " " + logger.debug("Retrieved metadata: " + meta.getParameterName() + " " +
meta.getParameterType() + " " + meta.getSqlType() + meta.getParameterType() + " " + meta.getSqlType() + " " +
" " + meta.getTypeName() + " " + meta.isNullable() meta.getTypeName() + " " + meta.isNullable());
);
} }
} }
} }
} }
catch (SQLException ex) { catch (SQLException ex) {
logger.warn("Error while retrieving metadata for procedure columns: " + ex); if (logger.isWarnEnabled()) {
logger.warn("Error while retrieving metadata for procedure columns: " + ex);
}
} }
finally { finally {
try { try {
@ -375,7 +380,9 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
} }
} }
catch (SQLException ex) { catch (SQLException ex) {
logger.warn("Problem closing ResultSet for procedure column metadata: " + ex); if (logger.isWarnEnabled()) {
logger.warn("Problem closing ResultSet for procedure column metadata: " + ex);
}
} }
} }
} }

View File

@ -68,8 +68,8 @@ public abstract class AnnotationConfigContextLoaderUtils {
else { else {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format( logger.debug(String.format(
"Ignoring class [%s]; it must be static, non-private, non-final, and annotated " "Ignoring class [%s]; it must be static, non-private, non-final, and annotated " +
+ "with @Configuration to be considered a default configuration class.", "with @Configuration to be considered a default configuration class.",
candidate.getName())); candidate.getName()));
} }
} }
@ -77,9 +77,9 @@ public abstract class AnnotationConfigContextLoaderUtils {
if (configClasses.isEmpty()) { if (configClasses.isEmpty()) {
if (logger.isInfoEnabled()) { if (logger.isInfoEnabled()) {
logger.info(String.format("Could not detect default configuration classes for test class [%s]: " logger.info(String.format("Could not detect default configuration classes for test class [%s]: " +
+ "%s does not declare any static, non-private, non-final, inner classes " "%s does not declare any static, non-private, non-final, inner classes " +
+ "annotated with @Configuration.", declaringClass.getName(), declaringClass.getSimpleName())); "annotated with @Configuration.", declaringClass.getName(), declaringClass.getSimpleName()));
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -47,14 +47,13 @@ final class SimpleStreamingClientHttpRequest extends AbstractClientHttpRequest {
private final boolean outputStreaming; private final boolean outputStreaming;
SimpleStreamingClientHttpRequest(HttpURLConnection connection, int chunkSize, SimpleStreamingClientHttpRequest(HttpURLConnection connection, int chunkSize, boolean outputStreaming) {
boolean outputStreaming) {
this.connection = connection; this.connection = connection;
this.chunkSize = chunkSize; this.chunkSize = chunkSize;
this.outputStreaming = outputStreaming; this.outputStreaming = outputStreaming;
} }
@Override
public HttpMethod getMethod() { public HttpMethod getMethod() {
return HttpMethod.valueOf(this.connection.getRequestMethod()); return HttpMethod.valueOf(this.connection.getRequestMethod());
} }

View File

@ -72,8 +72,11 @@ public class ControllerAdviceBean implements Ordered {
public ControllerAdviceBean(String beanName, BeanFactory beanFactory) { public ControllerAdviceBean(String beanName, BeanFactory beanFactory) {
Assert.hasText(beanName, "Bean name must not be null"); Assert.hasText(beanName, "Bean name must not be null");
Assert.notNull(beanFactory, "BeanFactory must not be null"); Assert.notNull(beanFactory, "BeanFactory must not be null");
Assert.isTrue(beanFactory.containsBean(beanName),
"BeanFactory [" + beanFactory + "] does not contain bean with name '" + beanName + "'"); if (!beanFactory.containsBean(beanName)) {
throw new IllegalArgumentException(
"BeanFactory [" + beanFactory + "] does not contain bean with name '" + beanName + "'");
}
this.bean = beanName; this.bean = beanName;
this.beanFactory = beanFactory; this.beanFactory = beanFactory;
@ -132,7 +135,7 @@ public class ControllerAdviceBean implements Ordered {
* Return a bean instance if necessary resolving the bean name through the BeanFactory. * Return a bean instance if necessary resolving the bean name through the BeanFactory.
*/ */
public Object resolveBean() { public Object resolveBean() {
return (this.bean instanceof String) ? this.beanFactory.getBean((String) this.bean) : this.bean; return (this.bean instanceof String ? this.beanFactory.getBean((String) this.bean) : this.bean);
} }
/** /**
@ -173,20 +176,14 @@ public class ControllerAdviceBean implements Ordered {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object other) {
if (this == o) { return (this == other ||
return true; (other instanceof ControllerAdviceBean && this.bean.equals(((ControllerAdviceBean) other).bean)));
}
if (o != null && o instanceof ControllerAdviceBean) {
ControllerAdviceBean other = (ControllerAdviceBean) o;
return this.bean.equals(other.bean);
}
return false;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return 31 * this.bean.hashCode(); return this.bean.hashCode();
} }
@Override @Override

View File

@ -616,7 +616,7 @@ final class HierarchicalUriComponents extends UriComponents {
@Override @Override
public String getPath() { public String getPath() {
return path; return this.path;
} }
@Override @Override

View File

@ -103,7 +103,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
for (String header : headers) { for (String header : headers) {
HeaderExpression expr = new HeaderExpression(header); HeaderExpression expr = new HeaderExpression(header);
if ("Accept".equalsIgnoreCase(expr.name)) { if ("Accept".equalsIgnoreCase(expr.name)) {
for ( MediaType mediaType : MediaType.parseMediaTypes(expr.value)) { for (MediaType mediaType : MediaType.parseMediaTypes(expr.value)) {
result.add(new ProduceMediaTypeExpression(mediaType, expr.isNegated)); result.add(new ProduceMediaTypeExpression(mediaType, expr.isNegated));
} }
} }
@ -161,7 +161,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
*/ */
@Override @Override
public ProducesRequestCondition combine(ProducesRequestCondition other) { public ProducesRequestCondition combine(ProducesRequestCondition other) {
return !other.expressions.isEmpty() ? other : this; return (!other.expressions.isEmpty() ? other : this);
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,7 +28,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Source; import javax.xml.transform.Source;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
@ -68,19 +67,24 @@ import org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionRes
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 3.1 * @since 3.1
*/ */
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver implements public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver
InitializingBean, ApplicationContextAware { implements ApplicationContextAware, InitializingBean {
private List<HandlerMethodArgumentResolver> customArgumentResolvers; private List<HandlerMethodArgumentResolver> customArgumentResolvers;
private HandlerMethodArgumentResolverComposite argumentResolvers;
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers; private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
private List<HttpMessageConverter<?>> messageConverters; private List<HttpMessageConverter<?>> messageConverters;
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager(); private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
private final List<Object> responseBodyAdvice = new ArrayList<Object>(); private final List<Object> responseBodyAdvice = new ArrayList<Object>();
private ApplicationContext applicationContext;
private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerCache = private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerCache =
new ConcurrentHashMap<Class<?>, ExceptionHandlerMethodResolver>(64); new ConcurrentHashMap<Class<?>, ExceptionHandlerMethodResolver>(64);
@ -88,17 +92,8 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
private final Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> exceptionHandlerAdviceCache = private final Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> exceptionHandlerAdviceCache =
new LinkedHashMap<ControllerAdviceBean, ExceptionHandlerMethodResolver>(); new LinkedHashMap<ControllerAdviceBean, ExceptionHandlerMethodResolver>();
private HandlerMethodArgumentResolverComposite argumentResolvers;
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
private ApplicationContext applicationContext;
/**
* Default constructor.
*/
public ExceptionHandlerExceptionResolver() { public ExceptionHandlerExceptionResolver() {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316 stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316
@ -109,18 +104,6 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
} }
/**
* Add one or more components to be invoked after the execution of a controller
* method annotated with {@code @ResponseBody} or returning {@code ResponseEntity}
* but before the body is written to the response with the selected
* {@code HttpMessageConverter}.
*/
public void setResponseBodyAdvice(List<ResponseBodyAdvice<?>> responseBodyAdvice) {
this.responseBodyAdvice.clear();
if (responseBodyAdvice != null) {
this.responseBodyAdvice.addAll(responseBodyAdvice);
}
}
/** /**
* Provide resolvers for custom argument types. Custom resolvers are ordered * Provide resolvers for custom argument types. Custom resolvers are ordered
@ -210,7 +193,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
* Return the configured message body converters. * Return the configured message body converters.
*/ */
public List<HttpMessageConverter<?>> getMessageConverters() { public List<HttpMessageConverter<?>> getMessageConverters() {
return messageConverters; return this.messageConverters;
} }
/** /**
@ -229,17 +212,20 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
} }
/** /**
* Return an unmodifiable Map with the {@link ControllerAdvice @ControllerAdvice} * Add one or more components to be invoked after the execution of a controller
* beans discovered in the ApplicationContext. The returned map will be empty if * method annotated with {@code @ResponseBody} or returning {@code ResponseEntity}
* the method is invoked before the bean has been initialized via * but before the body is written to the response with the selected
* {@link #afterPropertiesSet()}. * {@code HttpMessageConverter}.
*/ */
public Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> getExceptionHandlerAdviceCache() { public void setResponseBodyAdvice(List<ResponseBodyAdvice<?>> responseBodyAdvice) {
return Collections.unmodifiableMap(this.exceptionHandlerAdviceCache); this.responseBodyAdvice.clear();
if (responseBodyAdvice != null) {
this.responseBodyAdvice.addAll(responseBodyAdvice);
}
} }
@Override @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
} }
@ -249,7 +235,6 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
// Do this first, it may add ResponseBodyAdvice beans // Do this first, it may add ResponseBodyAdvice beans
initExceptionHandlerAdviceCache(); initExceptionHandlerAdviceCache();
@ -287,6 +272,16 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
} }
} }
/**
* Return an unmodifiable Map with the {@link ControllerAdvice @ControllerAdvice}
* beans discovered in the ApplicationContext. The returned map will be empty if
* the method is invoked before the bean has been initialized via
* {@link #afterPropertiesSet()}.
*/
public Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> getExceptionHandlerAdviceCache() {
return Collections.unmodifiableMap(this.exceptionHandlerAdviceCache);
}
/** /**
* Return the list of argument resolvers to use including built-in resolvers * Return the list of argument resolvers to use including built-in resolvers
* and custom resolvers provided via {@link #setCustomArgumentResolvers}. * and custom resolvers provided via {@link #setCustomArgumentResolvers}.
@ -365,7 +360,9 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception); exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception);
} }
catch (Exception invocationEx) { catch (Exception invocationEx) {
logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx); if (logger.isErrorEnabled()) {
logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
}
return null; return null;
} }
@ -388,12 +385,13 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
* and if not found, it continues searching for additional {@code @ExceptionHandler} * and if not found, it continues searching for additional {@code @ExceptionHandler}
* methods assuming some {@linkplain ControllerAdvice @ControllerAdvice} * methods assuming some {@linkplain ControllerAdvice @ControllerAdvice}
* Spring-managed beans were detected. * Spring-managed beans were detected.
* @param handlerMethod the method where the exception was raised, possibly {@code null} * @param handlerMethod the method where the exception was raised (may be {@code null})
* @param exception the raised exception * @param exception the raised exception
* @return a method to handle the exception, or {@code null} * @return a method to handle the exception, or {@code null}
*/ */
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) { protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) {
Class<?> handlerType = (handlerMethod != null) ? handlerMethod.getBeanType() : null; Class<?> handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null);
if (handlerMethod != null) { if (handlerMethod != null) {
ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType); ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType);
if (resolver == null) { if (resolver == null) {
@ -405,6 +403,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method); return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method);
} }
} }
for (Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry : this.exceptionHandlerAdviceCache.entrySet()) { for (Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry : this.exceptionHandlerAdviceCache.entrySet()) {
if (entry.getKey().isApplicableToBeanType(handlerType)) { if (entry.getKey().isApplicableToBeanType(handlerType)) {
ExceptionHandlerMethodResolver resolver = entry.getValue(); ExceptionHandlerMethodResolver resolver = entry.getValue();
@ -414,6 +413,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
} }
} }
} }
return null; return null;
} }