Polishing

This commit is contained in:
Juergen Hoeller 2014-10-20 17:42:18 +02:00
parent 10328f1c22
commit 77a62ec8b8
4 changed files with 73 additions and 102 deletions

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");
* you may not use this file except in compliance with the License.
@ -49,11 +49,12 @@ public class BeanInstantiationException extends FatalBeanException {
this.beanClass = beanClass;
}
/**
* Return the offending bean class.
*/
public Class<?> getBeanClass() {
return beanClass;
return this.beanClass;
}
}

View File

@ -410,7 +410,7 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
}
/**
* Kick off bean registration automatically when deployed in an {@code ApplicationContext}.
* Kick off bean registration automatically after the regular singleton instantiation phase.
* @see #registerBeans()
*/
@Override

View File

@ -45,8 +45,8 @@ import org.springframework.util.ObjectUtils;
* {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners},
* and {@link org.springframework.test.context.ActiveProfiles @ActiveProfiles}
* which offer support for merging and overriding various <em>inherited</em>
* annotation attributes (e.g., {@link
* org.springframework.test.context.ContextConfiguration#inheritLocations}).
* annotation attributes (e.g.
* {@link org.springframework.test.context.ContextConfiguration#inheritLocations}).
*
* @author Sam Brannen
* @since 4.0
@ -55,35 +55,26 @@ import org.springframework.util.ObjectUtils;
*/
public abstract class MetaAnnotationUtils {
private MetaAnnotationUtils() {
/* no-op */
}
/**
* Find the {@link AnnotationDescriptor} for the supplied {@code annotationType}
* on the supplied {@link Class}, traversing its annotations and superclasses
* if no annotation can be found on the given class itself.
*
* <p>This method explicitly handles class-level annotations which are not
* declared as {@linkplain java.lang.annotation.Inherited inherited} <em>as
* well as meta-annotations</em>.
*
* <p>The algorithm operates as follows:
* <ol>
* <li>Search for the annotation on the given class and return a corresponding
* {@code AnnotationDescriptor} if found.
* <li>Recursively search through all annotations that the given class declares.
* <li>Recursively search through the superclass hierarchy of the given class.
* <li>Search for the annotation on the given class and return a corresponding
* {@code AnnotationDescriptor} if found.
* <li>Recursively search through all annotations that the given class declares.
* <li>Recursively search through the superclass hierarchy of the given class.
* </ol>
*
* <p>In this context, the term <em>recursively</em> means that the search
* process continues by returning to step #1 with the current annotation or
* superclass as the class to look for annotations on.
*
* <p>If the supplied {@code clazz} is an interface, only the interface
* itself will be checked; the inheritance hierarchy for interfaces will not
* be traversed.
*
* @param clazz the class to look for annotations on
* @param annotationType the type of annotation to look for
* @return the corresponding annotation descriptor if the annotation was found;
@ -91,8 +82,9 @@ public abstract class MetaAnnotationUtils {
* @see AnnotationUtils#findAnnotationDeclaringClass(Class, Class)
* @see #findAnnotationDescriptorForTypes(Class, Class...)
*/
public static <T extends Annotation> AnnotationDescriptor<T> findAnnotationDescriptor(Class<?> clazz,
Class<T> annotationType) {
public static <T extends Annotation> AnnotationDescriptor<T> findAnnotationDescriptor(
Class<?> clazz, Class<T> annotationType) {
return findAnnotationDescriptor(clazz, new HashSet<Annotation>(), annotationType);
}
@ -100,7 +92,6 @@ public abstract class MetaAnnotationUtils {
* Perform the search algorithm for {@link #findAnnotationDescriptor(Class, Class)},
* avoiding endless recursion by tracking which annotations have already been
* <em>visited</em>.
*
* @param clazz the class to look for annotations on
* @param visited the set of annotations that have already been visited
* @param annotationType the type of annotation to look for
@ -142,31 +133,25 @@ public abstract class MetaAnnotationUtils {
* in the inheritance hierarchy of the specified {@code clazz} (including
* the specified {@code clazz} itself) which declares at least one of the
* specified {@code annotationTypes}.
*
* <p>This method traverses the annotations and superclasses of the specified
* {@code clazz} if no annotation can be found on the given class itself.
*
* <p>This method explicitly handles class-level annotations which are not
* declared as {@linkplain java.lang.annotation.Inherited inherited} <em>as
* well as meta-annotations</em>.
*
* <p>The algorithm operates as follows:
* <ol>
* <li>Search for a local declaration of one of the annotation types on
* the given class and return a corresponding {@code UntypedAnnotationDescriptor}
* if found.
* <li>Recursively search through all annotations that the given class declares.
* <li>Recursively search through the superclass hierarchy of the given class.
* <li>Search for a local declaration of one of the annotation types on
* the given class and return a corresponding {@code UntypedAnnotationDescriptor}
* if found.
* <li>Recursively search through all annotations that the given class declares.
* <li>Recursively search through the superclass hierarchy of the given class.
* </ol>
*
* <p>In this context, the term <em>recursively</em> means that the search
* process continues by returning to step #1 with the current annotation or
* superclass as the class to look for annotations on.
*
* <p>If the supplied {@code clazz} is an interface, only the interface
* itself will be checked; the inheritance hierarchy for interfaces will not
* be traversed.
*
* @param clazz the class to look for annotations on
* @param annotationTypes the types of annotations to look for
* @return the corresponding annotation descriptor if one of the annotations
@ -175,8 +160,9 @@ public abstract class MetaAnnotationUtils {
* @see #findAnnotationDescriptor(Class, Class)
*/
@SuppressWarnings("unchecked")
public static UntypedAnnotationDescriptor findAnnotationDescriptorForTypes(Class<?> clazz,
Class<? extends Annotation>... annotationTypes) {
public static UntypedAnnotationDescriptor findAnnotationDescriptorForTypes(
Class<?> clazz, Class<? extends Annotation>... annotationTypes) {
return findAnnotationDescriptorForTypes(clazz, new HashSet<Annotation>(), annotationTypes);
}
@ -184,7 +170,6 @@ public abstract class MetaAnnotationUtils {
* Perform the search algorithm for {@link #findAnnotationDescriptorForTypes(Class, Class...)},
* avoiding endless recursion by tracking which annotations have already been
* <em>visited</em>.
*
* @param clazz the class to look for annotations on
* @param visited the set of annotations that have already been visited
* @param annotationTypes the types of annotations to look for
@ -196,7 +181,6 @@ public abstract class MetaAnnotationUtils {
Set<Annotation> visited, Class<? extends Annotation>... annotationTypes) {
assertNonEmptyAnnotationTypeArray(annotationTypes, "The list of annotation types must not be empty");
if (clazz == null || clazz.equals(Object.class)) {
return null;
}
@ -224,49 +208,50 @@ public abstract class MetaAnnotationUtils {
return findAnnotationDescriptorForTypes(clazz.getSuperclass(), visited, annotationTypes);
}
private static void assertNonEmptyAnnotationTypeArray(Class<?>[] annotationTypes, String message) {
if (ObjectUtils.isEmpty(annotationTypes)) {
throw new IllegalArgumentException(message);
}
for (Class<?> clazz : annotationTypes) {
if (!Annotation.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException("Array elements must be of type Annotation");
}
}
}
/**
* Descriptor for an {@link Annotation}, including the {@linkplain
* #getDeclaringClass() class} on which the annotation is <em>declared</em>
* as well as the actual {@linkplain #getAnnotation() annotation} instance.
*
* <p>
* If the annotation is used as a meta-annotation, the descriptor also includes
* <p>If the annotation is used as a meta-annotation, the descriptor also includes
* the {@linkplain #getComposedAnnotation() composed annotation} on which the
* annotation is present. In such cases, the <em>root declaring class</em> is
* not directly annotated with the annotation but rather indirectly via the
* composed annotation.
*
* <p>
* Given the following example, if we are searching for the {@code @Transactional}
* <p>Given the following example, if we are searching for the {@code @Transactional}
* annotation <em>on</em> the {@code TransactionalTests} class, then the
* properties of the {@code AnnotationDescriptor} would be as follows.
*
* <ul>
* <li>rootDeclaringClass: {@code TransactionalTests} class object</li>
* <li>declaringClass: {@code TransactionalTests} class object</li>
* <li>composedAnnotation: {@code null}</li>
* <li>annotation: instance of the {@code Transactional} annotation</li>
* <li>rootDeclaringClass: {@code TransactionalTests} class object</li>
* <li>declaringClass: {@code TransactionalTests} class object</li>
* <li>composedAnnotation: {@code null}</li>
* <li>annotation: instance of the {@code Transactional} annotation</li>
* </ul>
*
* <pre style="code">
* &#064;Transactional
* &#064;ContextConfiguration({"/test-datasource.xml", "/repository-config.xml"})
* public class TransactionalTests { }
* </pre>
*
* <p>
* Given the following example, if we are searching for the {@code @Transactional}
* <p>Given the following example, if we are searching for the {@code @Transactional}
* annotation <em>on</em> the {@code UserRepositoryTests} class, then the
* properties of the {@code AnnotationDescriptor} would be as follows.
*
* <ul>
* <li>rootDeclaringClass: {@code UserRepositoryTests} class object</li>
* <li>declaringClass: {@code RepositoryTests} class object</li>
* <li>composedAnnotation: instance of the {@code RepositoryTests} annotation</li>
* <li>annotation: instance of the {@code Transactional} annotation</li>
* <li>rootDeclaringClass: {@code UserRepositoryTests} class object</li>
* <li>declaringClass: {@code RepositoryTests} class object</li>
* <li>composedAnnotation: instance of the {@code RepositoryTests} annotation</li>
* <li>annotation: instance of the {@code Transactional} annotation</li>
* </ul>
*
* <pre style="code">
* &#064;Transactional
* &#064;ContextConfiguration({"/test-datasource.xml", "/repository-config.xml"})
@ -276,18 +261,18 @@ public abstract class MetaAnnotationUtils {
* &#064;RepositoryTests
* public class UserRepositoryTests { }
* </pre>
*
* @author Sam Brannen
* @since 4.0
*/
public static class AnnotationDescriptor<T extends Annotation> {
private final Class<?> rootDeclaringClass;
private final Class<?> declaringClass;
private final Annotation composedAnnotation;
private final T annotation;
private final AnnotationAttributes annotationAttributes;
private final Class<?> declaringClass;
private final Annotation composedAnnotation;
private final T annotation;
private final AnnotationAttributes annotationAttributes;
public AnnotationDescriptor(Class<?> rootDeclaringClass, T annotation) {
this(rootDeclaringClass, rootDeclaringClass, null, annotation);
@ -297,13 +282,12 @@ public abstract class MetaAnnotationUtils {
Annotation composedAnnotation, T annotation) {
Assert.notNull(rootDeclaringClass, "rootDeclaringClass must not be null");
Assert.notNull(annotation, "annotation must not be null");
this.rootDeclaringClass = rootDeclaringClass;
this.declaringClass = declaringClass;
this.composedAnnotation = composedAnnotation;
this.annotation = annotation;
this.annotationAttributes = AnnotatedElementUtils.getAnnotationAttributes(rootDeclaringClass,
annotation.annotationType().getName());
this.annotationAttributes = AnnotatedElementUtils.getAnnotationAttributes(
rootDeclaringClass, annotation.annotationType().getName());
}
public Class<?> getRootDeclaringClass() {
@ -331,7 +315,7 @@ public abstract class MetaAnnotationUtils {
}
public Class<? extends Annotation> getComposedAnnotationType() {
return this.composedAnnotation == null ? null : this.composedAnnotation.annotationType();
return (this.composedAnnotation != null ? this.composedAnnotation.annotationType() : null);
}
/**
@ -339,22 +323,20 @@ public abstract class MetaAnnotationUtils {
*/
@Override
public String toString() {
return new ToStringCreator(this)//
.append("rootDeclaringClass", rootDeclaringClass)//
.append("declaringClass", declaringClass)//
.append("composedAnnotation", composedAnnotation)//
.append("annotation", annotation)//
.toString();
return new ToStringCreator(this)
.append("rootDeclaringClass", this.rootDeclaringClass)
.append("declaringClass", this.declaringClass)
.append("composedAnnotation", this.composedAnnotation)
.append("annotation", this.annotation)
.toString();
}
}
/**
* <em>Untyped</em> extension of {@code AnnotationDescriptor} that is used
* to describe the declaration of one of several candidate annotation types
* where the actual annotation type cannot be predetermined.
*
* @author Sam Brannen
* @since 4.0
*/
public static class UntypedAnnotationDescriptor extends AnnotationDescriptor<Annotation> {
@ -368,17 +350,4 @@ public abstract class MetaAnnotationUtils {
}
}
private static void assertNonEmptyAnnotationTypeArray(Class<?>[] annotationTypes, String message) {
if (ObjectUtils.isEmpty(annotationTypes)) {
throw new IllegalArgumentException(message);
}
for (Class<?> clazz : annotationTypes) {
if (!Annotation.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException("Array elements must be of type Annotation");
}
}
}
}

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");
* you may not use this file except in compliance with the License.
@ -26,23 +26,24 @@ import org.springframework.util.Assert;
import org.springframework.web.context.ServletContextAware;
/**
* A FactoryBean for configuring {@link javax.websocket.server.ServerContainer}. Since
* there is only one {@code ServerContainer} instance accessible under a well-known
* {@code javax.servlet.ServletContext} attribute, simply declaring this FactoryBean and
* using its setters allows configuring the {@code ServerContainer} through Spring
* configuration.
* A {@link FactoryBean} for configuring {@link javax.websocket.server.ServerContainer}.
* Since there is usually only one {@code ServerContainer} instance accessible under a
* well-known {@code javax.servlet.ServletContext} attribute, simply declaring this
* FactoryBean and using its setters allows for configuring the {@code ServerContainer}
* through Spring configuration.
*
* <p>This is useful even if the {@code ServerContainer} is not injected into any other
* bean. For example, an application can configure a {@link org.springframework.web.socket.server.support.DefaultHandshakeHandler}, a
* {@link org.springframework.web.socket.sockjs.SockJsService}, or {@link ServerEndpointExporter},
* and separately declare this FactoryBean in order to customize the properties of the
* (one and only) {@code ServerContainer} instance.
* bean within the Spring application context. For example, an application can configure
* a {@link org.springframework.web.socket.server.support.DefaultHandshakeHandler},
* a {@link org.springframework.web.socket.sockjs.SockJsService}, or
* {@link ServerEndpointExporter}, and separately declare this FactoryBean in order
* to customize the properties of the (one and only) {@code ServerContainer} instance.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
public class ServletServerContainerFactoryBean
implements FactoryBean<WebSocketContainer>, InitializingBean, ServletContextAware {
implements FactoryBean<WebSocketContainer>, ServletContextAware, InitializingBean {
private Long asyncSendTimeout;
@ -120,7 +121,7 @@ public class ServletServerContainerFactoryBean
@Override
public Class<?> getObjectType() {
return ServerContainer.class;
return (this.serverContainer != null ? this.serverContainer.getClass() : ServerContainer.class);
}
@Override