Synthesize annotation from a map of attributes
Spring Framework 4.2 RC1 introduced support for synthesizing an annotation from an existing annotation in order to provide additional functionality above and beyond that provided by Java. Specifically, such synthesized annotations provide support for @AliasFor semantics. As luck would have it, the same principle can be used to synthesize an annotation from any map of attributes, and in particular, from an instance of AnnotationAttributes. The following highlight the major changes in this commit toward achieving this goal. - Introduced AnnotationAttributeExtractor abstraction and refactored SynthesizedAnnotationInvocationHandler to delegate to an AnnotationAttributeExtractor. - Extracted code from SynthesizedAnnotationInvocationHandler into new AbstractAliasAwareAnnotationAttributeExtractor and DefaultAnnotationAttributeExtractor implementation classes. - Introduced MapAnnotationAttributeExtractor for synthesizing an annotation that is backed by a map or AnnotationAttributes instance. - Introduced a variant of synthesizeAnnotation() in AnnotationUtils that accepts a map. - Introduced findAnnotation(*) methods in AnnotatedElementUtils that synthesize merged AnnotationAttributes back into an annotation of the target type. The following classes have been refactored to use the new support for synthesizing AnnotationAttributes back into an annotation. - ApplicationListenerMethodAdapter - TestAnnotationUtils - AbstractTestContextBootstrapper - ActiveProfilesUtils - ContextLoaderUtils - DefaultActiveProfilesResolver - DirtiesContextTestExecutionListener - TestPropertySourceAttributes - TestPropertySourceUtils - TransactionalTestExecutionListener - MetaAnnotationUtils - MvcUriComponentsBuilder - RequestMappingHandlerMapping In addition, this commit also includes changes to ensure that arrays returned by synthesized annotations are properly cloned first. Issue: SPR-13067
This commit is contained in:
@@ -19,7 +19,6 @@ package org.springframework.test.annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
/**
|
||||
@@ -38,13 +37,12 @@ public class TestAnnotationUtils {
|
||||
* annotated with {@code @Timed}
|
||||
*/
|
||||
public static long getTimeout(Method method) {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.findAnnotationAttributes(method, Timed.class.getName());
|
||||
if (attributes == null) {
|
||||
Timed timed = AnnotatedElementUtils.findAnnotation(method, Timed.class);
|
||||
if (timed == null) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
long millis = attributes.<Long> getNumber("millis").longValue();
|
||||
return Math.max(0, millis);
|
||||
return Math.max(0, timed.millis());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ class MergedSqlConfig {
|
||||
|
||||
// Get global attributes, if any.
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.findAnnotationAttributes(testClass,
|
||||
SqlConfig.class.getName());
|
||||
SqlConfig.class.getName(), false, false);
|
||||
|
||||
// Override global attributes with local attributes.
|
||||
if (attributes != null) {
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
@@ -115,7 +114,6 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final List<TestExecutionListener> getTestExecutionListeners() {
|
||||
Class<?> clazz = getBootstrapContext().getTestClass();
|
||||
@@ -139,23 +137,20 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
// Traverse the class hierarchy...
|
||||
while (descriptor != null) {
|
||||
Class<?> declaringClass = descriptor.getDeclaringClass();
|
||||
AnnotationAttributes annAttrs = descriptor.getAnnotationAttributes();
|
||||
TestExecutionListeners testExecutionListeners = descriptor.getMergedAnnotation();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format(
|
||||
"Retrieved @TestExecutionListeners attributes [%s] for declaring class [%s].", annAttrs,
|
||||
declaringClass.getName()));
|
||||
logger.trace(String.format("Retrieved @TestExecutionListeners [%s] for declaring class [%s].",
|
||||
testExecutionListeners, declaringClass.getName()));
|
||||
}
|
||||
|
||||
Class<? extends TestExecutionListener>[] listenerClasses = (Class<? extends TestExecutionListener>[]) annAttrs.getClassArray("listeners");
|
||||
|
||||
boolean inheritListeners = annAttrs.getBoolean("inheritListeners");
|
||||
boolean inheritListeners = testExecutionListeners.inheritListeners();
|
||||
AnnotationDescriptor<TestExecutionListeners> superDescriptor = MetaAnnotationUtils.findAnnotationDescriptor(
|
||||
descriptor.getRootDeclaringClass().getSuperclass(), annotationType);
|
||||
|
||||
// If there are no listeners to inherit, we might need to merge the
|
||||
// locally declared listeners with the defaults.
|
||||
if ((!inheritListeners || superDescriptor == null)
|
||||
&& (annAttrs.getEnum("mergeMode") == MergeMode.MERGE_WITH_DEFAULTS)) {
|
||||
&& (testExecutionListeners.mergeMode() == MergeMode.MERGE_WITH_DEFAULTS)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format(
|
||||
"Merging default listeners with listeners configured via @TestExecutionListeners for class [%s].",
|
||||
@@ -165,7 +160,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
classesList.addAll(getDefaultTestExecutionListenerClasses());
|
||||
}
|
||||
|
||||
classesList.addAll(0, Arrays.<Class<? extends TestExecutionListener>> asList(listenerClasses));
|
||||
classesList.addAll(0, Arrays.asList(testExecutionListeners.listeners()));
|
||||
|
||||
descriptor = (inheritListeners ? superDescriptor : null);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.ActiveProfilesResolver;
|
||||
import org.springframework.test.util.MetaAnnotationUtils;
|
||||
@@ -87,14 +86,14 @@ abstract class ActiveProfilesUtils {
|
||||
while (descriptor != null) {
|
||||
Class<?> rootDeclaringClass = descriptor.getRootDeclaringClass();
|
||||
Class<?> declaringClass = descriptor.getDeclaringClass();
|
||||
ActiveProfiles annotation = descriptor.getMergedAnnotation();
|
||||
|
||||
AnnotationAttributes annAttrs = descriptor.getAnnotationAttributes();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Retrieved @ActiveProfiles attributes [%s] for declaring class [%s].",
|
||||
annAttrs, declaringClass.getName()));
|
||||
logger.trace(String.format("Retrieved @ActiveProfiles [%s] for declaring class [%s].", annotation,
|
||||
declaringClass.getName()));
|
||||
}
|
||||
|
||||
Class<? extends ActiveProfilesResolver> resolverClass = annAttrs.getClass("resolver");
|
||||
Class<? extends ActiveProfilesResolver> resolverClass = annotation.resolver();
|
||||
if (ActiveProfilesResolver.class == resolverClass) {
|
||||
resolverClass = DefaultActiveProfilesResolver.class;
|
||||
}
|
||||
@@ -125,8 +124,8 @@ abstract class ActiveProfilesUtils {
|
||||
}
|
||||
}
|
||||
|
||||
descriptor = annAttrs.getBoolean("inheritProfiles") ? MetaAnnotationUtils.findAnnotationDescriptor(
|
||||
rootDeclaringClass.getSuperclass(), annotationType) : null;
|
||||
descriptor = (annotation.inheritProfiles() ? MetaAnnotationUtils.findAnnotationDescriptor(
|
||||
rootDeclaringClass.getSuperclass(), annotationType) : null);
|
||||
}
|
||||
|
||||
return StringUtils.toStringArray(activeProfiles);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 +26,6 @@ import java.util.Set;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.ContextHierarchy;
|
||||
@@ -133,8 +132,9 @@ abstract class ContextLoaderUtils {
|
||||
final List<ContextConfigurationAttributes> configAttributesList = new ArrayList<ContextConfigurationAttributes>();
|
||||
|
||||
if (contextConfigDeclaredLocally) {
|
||||
convertAnnotationAttributesToConfigAttributesAndAddToList(descriptor.getAnnotationAttributes(),
|
||||
rootDeclaringClass, configAttributesList);
|
||||
convertContextConfigToConfigAttributesAndAddToList(
|
||||
(ContextConfiguration) descriptor.getMergedAnnotation(), rootDeclaringClass,
|
||||
configAttributesList);
|
||||
}
|
||||
else if (contextHierarchyDeclaredLocally) {
|
||||
ContextHierarchy contextHierarchy = getAnnotation(declaringClass, contextHierarchyType);
|
||||
@@ -256,7 +256,7 @@ abstract class ContextLoaderUtils {
|
||||
annotationType.getName(), testClass.getName()));
|
||||
|
||||
while (descriptor != null) {
|
||||
convertAnnotationAttributesToConfigAttributesAndAddToList(descriptor.getAnnotationAttributes(),
|
||||
convertContextConfigToConfigAttributesAndAddToList(descriptor.getMergedAnnotation(),
|
||||
descriptor.getRootDeclaringClass(), attributesList);
|
||||
descriptor = findAnnotationDescriptor(descriptor.getRootDeclaringClass().getSuperclass(), annotationType);
|
||||
}
|
||||
@@ -284,24 +284,4 @@ abstract class ContextLoaderUtils {
|
||||
attributesList.add(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for creating a {@link ContextConfigurationAttributes}
|
||||
* instance from the supplied {@link AnnotationAttributes} and declaring
|
||||
* class and then adding the attributes to the supplied list.
|
||||
* @since 4.0
|
||||
*/
|
||||
private static void convertAnnotationAttributesToConfigAttributesAndAddToList(AnnotationAttributes annAttrs,
|
||||
Class<?> declaringClass, final List<ContextConfigurationAttributes> attributesList) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Retrieved @ContextConfiguration attributes [%s] for declaring class [%s].",
|
||||
annAttrs, declaringClass.getName()));
|
||||
}
|
||||
|
||||
ContextConfigurationAttributes attributes = new ContextConfigurationAttributes(declaringClass, annAttrs);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Resolved context configuration attributes: " + attributes);
|
||||
}
|
||||
attributesList.add(attributes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ import java.util.Set;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.ActiveProfilesResolver;
|
||||
import org.springframework.test.util.MetaAnnotationUtils.AnnotationDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -73,14 +73,14 @@ public class DefaultActiveProfilesResolver implements ActiveProfilesResolver {
|
||||
}
|
||||
else {
|
||||
Class<?> declaringClass = descriptor.getDeclaringClass();
|
||||
ActiveProfiles annotation = descriptor.getMergedAnnotation();
|
||||
|
||||
AnnotationAttributes annAttrs = descriptor.getAnnotationAttributes();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Retrieved @ActiveProfiles attributes [%s] for declaring class [%s].",
|
||||
annAttrs, declaringClass.getName()));
|
||||
logger.trace(String.format("Retrieved @ActiveProfiles [%s] for declaring class [%s].", annotation,
|
||||
declaringClass.getName()));
|
||||
}
|
||||
|
||||
for (String profile : annAttrs.getStringArray("profiles")) {
|
||||
for (String profile : annotation.profiles()) {
|
||||
if (StringUtils.hasText(profile)) {
|
||||
activeProfiles.add(profile.trim());
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||
import org.springframework.test.annotation.DirtiesContext.HierarchyMode;
|
||||
@@ -150,28 +149,27 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi
|
||||
*/
|
||||
private void beforeOrAfterTestMethod(TestContext testContext, String phase, MethodMode requiredMethodMode,
|
||||
ClassMode requiredClassMode) throws Exception {
|
||||
|
||||
Class<?> testClass = testContext.getTestClass();
|
||||
Assert.notNull(testClass, "The test class of the supplied TestContext must not be null");
|
||||
Method testMethod = testContext.getTestMethod();
|
||||
Assert.notNull(testClass, "The test class of the supplied TestContext must not be null");
|
||||
Assert.notNull(testMethod, "The test method of the supplied TestContext must not be null");
|
||||
|
||||
final String annotationType = DirtiesContext.class.getName();
|
||||
AnnotationAttributes methodAnnAttrs = AnnotatedElementUtils.findAnnotationAttributes(testMethod, annotationType);
|
||||
AnnotationAttributes classAnnAttrs = AnnotatedElementUtils.findAnnotationAttributes(testClass, annotationType);
|
||||
boolean methodAnnotated = methodAnnAttrs != null;
|
||||
boolean classAnnotated = classAnnAttrs != null;
|
||||
MethodMode methodMode = methodAnnotated ? methodAnnAttrs.<MethodMode> getEnum("methodMode") : null;
|
||||
ClassMode classMode = classAnnotated ? classAnnAttrs.<ClassMode> getEnum("classMode") : null;
|
||||
DirtiesContext methodAnn = AnnotatedElementUtils.findAnnotation(testMethod, DirtiesContext.class);
|
||||
DirtiesContext classAnn = AnnotatedElementUtils.findAnnotation(testClass, DirtiesContext.class);
|
||||
boolean methodAnnotated = (methodAnn != null);
|
||||
boolean classAnnotated = (classAnn != null);
|
||||
MethodMode methodMode = (methodAnnotated ? methodAnn.methodMode() : null);
|
||||
ClassMode classMode = (classAnnotated ? classAnn.classMode() : null);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format(
|
||||
"%s test method: context %s, class annotated with @DirtiesContext [%s] with mode [%s], method annotated with @DirtiesContext [%s] with mode [%s].",
|
||||
phase, testContext, classAnnotated, classMode, methodAnnotated, methodMode));
|
||||
logger.debug(String.format("%s test method: context %s, class annotated with @DirtiesContext [%s] "
|
||||
+ "with mode [%s], method annotated with @DirtiesContext [%s] with mode [%s].", phase, testContext,
|
||||
classAnnotated, classMode, methodAnnotated, methodMode));
|
||||
}
|
||||
|
||||
if ((methodMode == requiredMethodMode) || (classMode == requiredClassMode)) {
|
||||
HierarchyMode hierarchyMode = methodAnnotated ? methodAnnAttrs.<HierarchyMode> getEnum("hierarchyMode")
|
||||
: classAnnAttrs.<HierarchyMode> getEnum("hierarchyMode");
|
||||
HierarchyMode hierarchyMode = (methodAnnotated ? methodAnn.hierarchyMode() : classAnn.hierarchyMode());
|
||||
dirtyContext(testContext, hierarchyMode);
|
||||
}
|
||||
}
|
||||
@@ -185,10 +183,9 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi
|
||||
Class<?> testClass = testContext.getTestClass();
|
||||
Assert.notNull(testClass, "The test class of the supplied TestContext must not be null");
|
||||
|
||||
final String annotationType = DirtiesContext.class.getName();
|
||||
AnnotationAttributes classAnnAttrs = AnnotatedElementUtils.findAnnotationAttributes(testClass, annotationType);
|
||||
boolean classAnnotated = classAnnAttrs != null;
|
||||
ClassMode classMode = classAnnotated ? classAnnAttrs.<ClassMode> getEnum("classMode") : null;
|
||||
DirtiesContext dirtiesContext = AnnotatedElementUtils.findAnnotation(testClass, DirtiesContext.class);
|
||||
boolean classAnnotated = (dirtiesContext != null);
|
||||
ClassMode classMode = (classAnnotated ? dirtiesContext.classMode() : null);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format(
|
||||
@@ -197,8 +194,7 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi
|
||||
}
|
||||
|
||||
if (classMode == requiredClassMode) {
|
||||
HierarchyMode hierarchyMode = classAnnAttrs.<HierarchyMode> getEnum("hierarchyMode");
|
||||
dirtyContext(testContext, hierarchyMode);
|
||||
dirtyContext(testContext, dirtiesContext.hierarchyMode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.test.context.support;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
@@ -58,17 +57,17 @@ class TestPropertySourceAttributes {
|
||||
|
||||
/**
|
||||
* Create a new {@code TestPropertySourceAttributes} instance for the
|
||||
* supplied {@link AnnotationAttributes} (parsed from a
|
||||
* {@link TestPropertySource @TestPropertySource} annotation) and
|
||||
* the {@linkplain Class test class} that declared them, enforcing
|
||||
* supplied {@link TestPropertySource @TestPropertySource} annotation and
|
||||
* the {@linkplain Class test class} that declared it, enforcing
|
||||
* configuration rules and detecting a default properties file if
|
||||
* necessary.
|
||||
* @param declaringClass the class that declared {@code @TestPropertySource}
|
||||
* @param annAttrs the annotation attributes from which to retrieve the attributes
|
||||
* @param testPropertySource the annotation from which to retrieve the attributes
|
||||
* @since 4.2
|
||||
*/
|
||||
TestPropertySourceAttributes(Class<?> declaringClass, AnnotationAttributes annAttrs) {
|
||||
this(declaringClass, annAttrs.getStringArray("locations"), annAttrs.getBoolean("inheritLocations"),
|
||||
annAttrs.getStringArray("properties"), annAttrs.getBoolean("inheritProperties"));
|
||||
TestPropertySourceAttributes(Class<?> declaringClass, TestPropertySource testPropertySource) {
|
||||
this(declaringClass, testPropertySource.locations(), testPropertySource.inheritLocations(),
|
||||
testPropertySource.properties(), testPropertySource.inheritProperties());
|
||||
}
|
||||
|
||||
private TestPropertySourceAttributes(Class<?> declaringClass, String[] locations, boolean inheritLocations,
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
@@ -39,6 +38,7 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourcePropertySource;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.util.TestContextResourceUtils;
|
||||
import org.springframework.test.util.MetaAnnotationUtils.AnnotationDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -96,15 +96,16 @@ public abstract class TestPropertySourceUtils {
|
||||
annotationType.getName(), testClass.getName()));
|
||||
|
||||
while (descriptor != null) {
|
||||
AnnotationAttributes annAttrs = descriptor.getAnnotationAttributes();
|
||||
TestPropertySource testPropertySource = descriptor.getMergedAnnotation();
|
||||
Class<?> rootDeclaringClass = descriptor.getRootDeclaringClass();
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Retrieved @TestPropertySource attributes [%s] for declaring class [%s].",
|
||||
annAttrs, rootDeclaringClass.getName()));
|
||||
logger.trace(String.format("Retrieved @TestPropertySource [%s] for declaring class [%s].",
|
||||
testPropertySource, rootDeclaringClass.getName()));
|
||||
}
|
||||
|
||||
TestPropertySourceAttributes attributes = new TestPropertySourceAttributes(rootDeclaringClass, annAttrs);
|
||||
TestPropertySourceAttributes attributes = new TestPropertySourceAttributes(rootDeclaringClass,
|
||||
testPropertySource);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Resolved TestPropertySource attributes: " + attributes);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
import org.springframework.test.context.TestContext;
|
||||
import org.springframework.test.context.support.AbstractTestExecutionListener;
|
||||
@@ -500,18 +499,18 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
|
||||
if (this.configurationAttributes == null) {
|
||||
Class<?> clazz = testContext.getTestClass();
|
||||
|
||||
AnnotationAttributes annAttrs = AnnotatedElementUtils.findAnnotationAttributes(clazz,
|
||||
TransactionConfiguration.class.getName());
|
||||
TransactionConfiguration txConfig = AnnotatedElementUtils.findAnnotation(clazz,
|
||||
TransactionConfiguration.class);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Retrieved @TransactionConfiguration attributes [%s] for test class [%s].",
|
||||
annAttrs, clazz));
|
||||
logger.debug(String.format("Retrieved @TransactionConfiguration [%s] for test class [%s].",
|
||||
txConfig, clazz));
|
||||
}
|
||||
|
||||
String transactionManagerName;
|
||||
boolean defaultRollback;
|
||||
if (annAttrs != null) {
|
||||
transactionManagerName = annAttrs.getString("transactionManager");
|
||||
defaultRollback = annAttrs.getBoolean("defaultRollback");
|
||||
if (txConfig != null) {
|
||||
transactionManagerName = txConfig.transactionManager();
|
||||
defaultRollback = txConfig.defaultRollback();
|
||||
}
|
||||
else {
|
||||
transactionManagerName = DEFAULT_TRANSACTION_MANAGER_NAME;
|
||||
|
||||
@@ -272,12 +272,16 @@ public abstract class MetaAnnotationUtils {
|
||||
|
||||
private final T annotation;
|
||||
|
||||
private final T mergedAnnotation;
|
||||
|
||||
private final AnnotationAttributes annotationAttributes;
|
||||
|
||||
|
||||
public AnnotationDescriptor(Class<?> rootDeclaringClass, T annotation) {
|
||||
this(rootDeclaringClass, rootDeclaringClass, null, annotation);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public AnnotationDescriptor(Class<?> rootDeclaringClass, Class<?> declaringClass,
|
||||
Annotation composedAnnotation, T annotation) {
|
||||
Assert.notNull(rootDeclaringClass, "rootDeclaringClass must not be null");
|
||||
@@ -286,8 +290,10 @@ public abstract class MetaAnnotationUtils {
|
||||
this.declaringClass = declaringClass;
|
||||
this.composedAnnotation = composedAnnotation;
|
||||
this.annotation = annotation;
|
||||
this.annotationAttributes = AnnotatedElementUtils.findAnnotationAttributes(
|
||||
rootDeclaringClass, annotation.annotationType());
|
||||
this.annotationAttributes = AnnotatedElementUtils.findAnnotationAttributes(rootDeclaringClass,
|
||||
annotation.annotationType().getName(), false, false);
|
||||
this.mergedAnnotation = AnnotationUtils.synthesizeAnnotation(annotationAttributes,
|
||||
(Class<T>) annotation.annotationType(), rootDeclaringClass);
|
||||
}
|
||||
|
||||
public Class<?> getRootDeclaringClass() {
|
||||
@@ -302,6 +308,16 @@ public abstract class MetaAnnotationUtils {
|
||||
return this.annotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the annotation that was synthesized from the merged
|
||||
* {@link #getAnnotationAttributes AnnotationAttributes}.
|
||||
* @see #getAnnotationAttributes()
|
||||
* @see AnnotationUtils#synthesizeAnnotation(java.util.Map, Class, java.lang.reflect.AnnotatedElement)
|
||||
*/
|
||||
public T getMergedAnnotation() {
|
||||
return this.mergedAnnotation;
|
||||
}
|
||||
|
||||
public Class<? extends Annotation> getAnnotationType() {
|
||||
return this.annotation.annotationType();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user