Polishing
This commit is contained in:
parent
7bc966032b
commit
8f484d382e
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 @Configurable, and
|
* for example) are unlikely to be marked as @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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -616,7 +616,7 @@ final class HierarchicalUriComponents extends UriComponents {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
return path;
|
return this.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue