Polishing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -123,15 +123,15 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
|
||||
/**
|
||||
* Find and return the first AspectJ annotation on the given method
|
||||
* (there <i>should</i> only be one anyway...)
|
||||
* (there <i>should</i> only be one anyway...).
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
|
||||
Class<?>[] classesToLookFor = new Class<?>[] {
|
||||
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
|
||||
for (Class<?> c : classesToLookFor) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
|
||||
for (Class<?> clazz : classesToLookFor) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
@@ -151,6 +151,9 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AspectJ annotation types.
|
||||
*/
|
||||
protected enum AspectJAnnotationType {
|
||||
|
||||
AtPointcut,
|
||||
|
||||
@@ -131,9 +131,14 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati
|
||||
Collection<CacheOperation> annOps = provider.getCacheOperations(annotationParser);
|
||||
if (annOps != null) {
|
||||
if (ops == null) {
|
||||
ops = new ArrayList<>();
|
||||
ops = annOps;
|
||||
}
|
||||
else {
|
||||
Collection<CacheOperation> combined = new ArrayList<>(ops.size() + annOps.size());
|
||||
combined.addAll(ops);
|
||||
combined.addAll(annOps);
|
||||
ops = combined;
|
||||
}
|
||||
ops.addAll(annOps);
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
|
||||
@@ -155,7 +155,7 @@ public class AnnotationConfigUtils {
|
||||
}
|
||||
}
|
||||
|
||||
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);
|
||||
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
|
||||
|
||||
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
|
||||
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
|
||||
@@ -202,6 +202,7 @@ public class AnnotationConfigUtils {
|
||||
def.setSource(source);
|
||||
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
|
||||
}
|
||||
|
||||
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
|
||||
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
|
||||
def.setSource(source);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,6 +24,7 @@ import org.springframework.core.Ordered;
|
||||
/**
|
||||
* Default {@link EventListenerFactory} implementation that supports the
|
||||
* regular {@link EventListener} annotation.
|
||||
*
|
||||
* <p>Used as "catch-all" implementation by default.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
@@ -33,15 +34,17 @@ public class DefaultEventListenerFactory implements EventListenerFactory, Ordere
|
||||
|
||||
private int order = LOWEST_PRECEDENCE;
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
|
||||
public boolean supportsMethod(Method method) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,8 +45,7 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Register {@link EventListener} annotated method as individual {@link ApplicationListener}
|
||||
* instances.
|
||||
* Registers {@link EventListener} methods as individual {@link ApplicationListener} instances.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -39,8 +39,6 @@ public abstract class Base64Utils {
|
||||
* Base64-encode the given byte array.
|
||||
* @param src the original byte array
|
||||
* @return the encoded byte array
|
||||
* @throws IllegalStateException if Base64 encoding between byte arrays is not
|
||||
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
|
||||
*/
|
||||
public static byte[] encode(byte[] src) {
|
||||
if (src.length == 0) {
|
||||
@@ -53,8 +51,6 @@ public abstract class Base64Utils {
|
||||
* Base64-decode the given byte array.
|
||||
* @param src the encoded byte array
|
||||
* @return the original byte array
|
||||
* @throws IllegalStateException if Base64 encoding between byte arrays is not
|
||||
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
|
||||
*/
|
||||
public static byte[] decode(byte[] src) {
|
||||
if (src.length == 0) {
|
||||
@@ -68,8 +64,6 @@ public abstract class Base64Utils {
|
||||
* "URL and Filename Safe Alphabet".
|
||||
* @param src the original byte array
|
||||
* @return the encoded byte array
|
||||
* @throws IllegalStateException if Base64 encoding between byte arrays is not
|
||||
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
|
||||
* @since 4.2.4
|
||||
*/
|
||||
public static byte[] encodeUrlSafe(byte[] src) {
|
||||
@@ -84,8 +78,6 @@ public abstract class Base64Utils {
|
||||
* "URL and Filename Safe Alphabet".
|
||||
* @param src the encoded byte array
|
||||
* @return the original byte array
|
||||
* @throws IllegalStateException if Base64 encoding between byte arrays is not
|
||||
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
|
||||
* @since 4.2.4
|
||||
*/
|
||||
public static byte[] decodeUrlSafe(byte[] src) {
|
||||
@@ -124,8 +116,6 @@ public abstract class Base64Utils {
|
||||
* "URL and Filename Safe Alphabet".
|
||||
* @param src the original byte array
|
||||
* @return the encoded byte array as a UTF-8 String
|
||||
* @throws IllegalStateException if Base64 encoding between byte arrays is not
|
||||
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
|
||||
*/
|
||||
public static String encodeToUrlSafeString(byte[] src) {
|
||||
return new String(encodeUrlSafe(src), DEFAULT_CHARSET);
|
||||
@@ -136,8 +126,6 @@ public abstract class Base64Utils {
|
||||
* "URL and Filename Safe Alphabet".
|
||||
* @param src the encoded UTF-8 String
|
||||
* @return the original byte array
|
||||
* @throws IllegalStateException if Base64 encoding between byte arrays is not
|
||||
* supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime
|
||||
*/
|
||||
public static byte[] decodeFromUrlSafeString(String src) {
|
||||
return decodeUrlSafe(src.getBytes(DEFAULT_CHARSET));
|
||||
|
||||
@@ -176,13 +176,15 @@ public class JdbcTemplateTests {
|
||||
|
||||
@Test
|
||||
public void testStringsWithEmptyPreparedStatementArgs() throws Exception {
|
||||
doTestStrings(null, null, null, null, (template, sql, rch) -> template.query(sql, (Object[]) null, rch));
|
||||
doTestStrings(null, null, null, null,
|
||||
(template, sql, rch) -> template.query(sql, (Object[]) null, rch));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringsWithPreparedStatementArgs() throws Exception {
|
||||
final Integer argument = 99;
|
||||
doTestStrings(null, null, null, argument, (template, sql, rch) -> template.query(sql, new Object[] { argument }, rch));
|
||||
doTestStrings(null, null, null, argument,
|
||||
(template, sql, rch) -> template.query(sql, new Object[] {argument}, rch));
|
||||
}
|
||||
|
||||
private void doTestStrings(Integer fetchSize, Integer maxRows, Integer queryTimeout,
|
||||
@@ -362,10 +364,10 @@ public class JdbcTemplateTests {
|
||||
given(this.preparedStatement.executeUpdate()).willReturn(rowsAffected);
|
||||
|
||||
int actualRowsAffected = this.template.update(sql,
|
||||
new Object[] {4, new SqlParameterValue(Types.NUMERIC, 2, new Float(1.4142))});
|
||||
4, new SqlParameterValue(Types.NUMERIC, 2, Float.valueOf(1.4142f)));
|
||||
assertTrue("Actual rows affected is correct", actualRowsAffected == rowsAffected);
|
||||
verify(this.preparedStatement).setObject(1, 4);
|
||||
verify(this.preparedStatement).setObject(2, new Float(1.4142), Types.NUMERIC, 2);
|
||||
verify(this.preparedStatement).setObject(2, Float.valueOf(1.4142f), Types.NUMERIC, 2);
|
||||
verify(this.preparedStatement).close();
|
||||
verify(this.connection).close();
|
||||
}
|
||||
@@ -427,8 +429,7 @@ public class JdbcTemplateTests {
|
||||
public void testBatchUpdateWithBatchFailure() throws Exception {
|
||||
final String[] sql = {"A", "B", "C", "D"};
|
||||
given(this.statement.executeBatch()).willThrow(
|
||||
new BatchUpdateException(new int[] { 1, Statement.EXECUTE_FAILED, 1,
|
||||
Statement.EXECUTE_FAILED }));
|
||||
new BatchUpdateException(new int[] {1, Statement.EXECUTE_FAILED, 1, Statement.EXECUTE_FAILED}));
|
||||
mockDatabaseMetaData(true);
|
||||
given(this.connection.createStatement()).willReturn(this.statement);
|
||||
|
||||
@@ -495,18 +496,16 @@ public class JdbcTemplateTests {
|
||||
given(this.preparedStatement.executeBatch()).willReturn(rowsAffected);
|
||||
mockDatabaseMetaData(true);
|
||||
|
||||
BatchPreparedStatementSetter setter =
|
||||
new BatchPreparedStatementSetter() {
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i)
|
||||
throws SQLException {
|
||||
ps.setInt(1, ids[i]);
|
||||
}
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return ids.length;
|
||||
}
|
||||
};
|
||||
BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter() {
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
ps.setInt(1, ids[i]);
|
||||
}
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return ids.length;
|
||||
}
|
||||
};
|
||||
|
||||
JdbcTemplate template = new JdbcTemplate(this.dataSource, false);
|
||||
|
||||
@@ -1049,10 +1048,9 @@ public class JdbcTemplateTests {
|
||||
}
|
||||
|
||||
try {
|
||||
this.template.query(con -> con.prepareStatement("my query"),
|
||||
(ResultSetExtractor<Object>) rs2 -> {
|
||||
throw new InvalidDataAccessApiUsageException("");
|
||||
} );
|
||||
this.template.query(con -> con.prepareStatement("my query"), (ResultSetExtractor<Object>) rs2 -> {
|
||||
throw new InvalidDataAccessApiUsageException("");
|
||||
});
|
||||
fail("Should have thrown InvalidDataAccessApiUsageException");
|
||||
}
|
||||
catch (InvalidDataAccessApiUsageException ex) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,11 +21,11 @@ import java.lang.reflect.Method;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.EventListenerFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
|
||||
/**
|
||||
* {@link EventListenerFactory} implementation that handles {@link TransactionalEventListener}
|
||||
* annotated method.
|
||||
* annotated methods.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.2
|
||||
@@ -47,7 +47,7 @@ public class TransactionalEventListenerFactory implements EventListenerFactory,
|
||||
|
||||
@Override
|
||||
public boolean supportsMethod(Method method) {
|
||||
return (AnnotationUtils.findAnnotation(method, TransactionalEventListener.class) != null);
|
||||
return AnnotatedElementUtils.hasAnnotation(method, TransactionalEventListener.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,13 +32,14 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -50,12 +51,11 @@ import org.springframework.web.reactive.result.method.InvocableHandlerMethod;
|
||||
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.SyncInvocableHandlerMethod;
|
||||
|
||||
import static org.springframework.core.MethodIntrospector.*;
|
||||
|
||||
/**
|
||||
* Package-private class to assist {@link RequestMappingHandlerAdapter} with
|
||||
* resolving, initializing, and caching annotated methods declared in
|
||||
* {@code @Controller} and {@code @ControllerAdvice} components:
|
||||
* {@code @Controller} and {@code @ControllerAdvice} components. Assists with
|
||||
* the following annotations:
|
||||
* <ul>
|
||||
* <li>{@code @InitBinder}
|
||||
* <li>{@code @ModelAttribute}
|
||||
@@ -68,8 +68,21 @@ import static org.springframework.core.MethodIntrospector.*;
|
||||
*/
|
||||
class ControllerMethodResolver {
|
||||
|
||||
private static Log logger = LogFactory.getLog(ControllerMethodResolver.class);
|
||||
/**
|
||||
* MethodFilter that matches {@link InitBinder @InitBinder} methods.
|
||||
*/
|
||||
private static final MethodFilter INIT_BINDER_METHODS = method ->
|
||||
(AnnotationUtils.findAnnotation(method, InitBinder.class) != null);
|
||||
|
||||
/**
|
||||
* MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods.
|
||||
*/
|
||||
private static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->
|
||||
(AnnotationUtils.findAnnotation(method, RequestMapping.class) == null) &&
|
||||
(AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null);
|
||||
|
||||
|
||||
private static Log logger = LogFactory.getLog(ControllerMethodResolver.class);
|
||||
|
||||
private final List<SyncHandlerMethodArgumentResolver> initBinderResolvers;
|
||||
|
||||
@@ -204,7 +217,6 @@ class ControllerMethodResolver {
|
||||
}
|
||||
|
||||
private void initControllerAdviceCaches(ApplicationContext applicationContext) {
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Looking for @ControllerAdvice: " + applicationContext);
|
||||
}
|
||||
@@ -215,14 +227,14 @@ class ControllerMethodResolver {
|
||||
for (ControllerAdviceBean bean : beans) {
|
||||
Class<?> beanType = bean.getBeanType();
|
||||
if (beanType != null) {
|
||||
Set<Method> attrMethods = selectMethods(beanType, ATTRIBUTE_METHODS);
|
||||
Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
|
||||
if (!attrMethods.isEmpty()) {
|
||||
this.modelAttributeAdviceCache.put(bean, attrMethods);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Detected @ModelAttribute methods in " + bean);
|
||||
}
|
||||
}
|
||||
Set<Method> binderMethods = selectMethods(beanType, BINDER_METHODS);
|
||||
Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
|
||||
if (!binderMethods.isEmpty()) {
|
||||
this.initBinderAdviceCache.put(bean, binderMethods);
|
||||
if (logger.isInfoEnabled()) {
|
||||
@@ -269,7 +281,8 @@ class ControllerMethodResolver {
|
||||
});
|
||||
|
||||
this.initBinderMethodCache
|
||||
.computeIfAbsent(handlerType, aClass -> selectMethods(handlerType, BINDER_METHODS))
|
||||
.computeIfAbsent(handlerType,
|
||||
clazz -> MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS))
|
||||
.forEach(method -> {
|
||||
Object bean = handlerMethod.getBean();
|
||||
result.add(getInitBinderMethod(bean, method));
|
||||
@@ -301,7 +314,8 @@ class ControllerMethodResolver {
|
||||
});
|
||||
|
||||
this.modelAttributeMethodCache
|
||||
.computeIfAbsent(handlerType, aClass -> selectMethods(handlerType, ATTRIBUTE_METHODS))
|
||||
.computeIfAbsent(handlerType,
|
||||
clazz -> MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS))
|
||||
.forEach(method -> {
|
||||
Object bean = handlerMethod.getBean();
|
||||
result.add(createAttributeMethod(bean, method));
|
||||
@@ -372,14 +386,4 @@ class ControllerMethodResolver {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** Filter for {@link InitBinder @InitBinder} methods. */
|
||||
private static final ReflectionUtils.MethodFilter BINDER_METHODS = method ->
|
||||
AnnotationUtils.findAnnotation(method, InitBinder.class) != null;
|
||||
|
||||
/** Filter for {@link ModelAttribute @ModelAttribute} methods. */
|
||||
private static final ReflectionUtils.MethodFilter ATTRIBUTE_METHODS = method ->
|
||||
(AnnotationUtils.findAnnotation(method, RequestMapping.class) == null) &&
|
||||
(AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null);
|
||||
|
||||
}
|
||||
|
||||
@@ -114,6 +114,20 @@ import org.springframework.web.util.WebUtils;
|
||||
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
implements BeanFactoryAware, InitializingBean {
|
||||
|
||||
/**
|
||||
* MethodFilter that matches {@link InitBinder @InitBinder} methods.
|
||||
*/
|
||||
public static final MethodFilter INIT_BINDER_METHODS = method ->
|
||||
(AnnotationUtils.findAnnotation(method, InitBinder.class) != null);
|
||||
|
||||
/**
|
||||
* MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods.
|
||||
*/
|
||||
public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->
|
||||
((AnnotationUtils.findAnnotation(method, RequestMapping.class) == null) &&
|
||||
(AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null));
|
||||
|
||||
|
||||
@Nullable
|
||||
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
|
||||
|
||||
@@ -1002,18 +1016,4 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
return mav;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MethodFilter that matches {@link InitBinder @InitBinder} methods.
|
||||
*/
|
||||
public static final MethodFilter INIT_BINDER_METHODS = method ->
|
||||
AnnotationUtils.findAnnotation(method, InitBinder.class) != null;
|
||||
|
||||
/**
|
||||
* MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods.
|
||||
*/
|
||||
public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->
|
||||
((AnnotationUtils.findAnnotation(method, RequestMapping.class) == null) &&
|
||||
(AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null));
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,31 +66,29 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
@Parameters(name = "controller [{0}], auto-proxy [{1}]")
|
||||
public static Object[][] handlerTypes() {
|
||||
return new Object[][] {
|
||||
{ SimpleController.class, true }, // CGLIB proxy
|
||||
{ SimpleController.class, false },
|
||||
|
||||
{ SimpleController.class, true }, // CGLib proxy
|
||||
{ SimpleController.class, false },
|
||||
{ AbstractClassController.class, true }, // CGLIB proxy
|
||||
{ AbstractClassController.class, false },
|
||||
|
||||
{ AbstractClassController.class, true }, // CGLib proxy
|
||||
{ AbstractClassController.class, false },
|
||||
{ ParameterizedAbstractClassController.class, true }, // CGLIB proxy
|
||||
{ ParameterizedAbstractClassController.class, false },
|
||||
|
||||
{ ParameterizedAbstractClassController.class, true }, // CGLib proxy
|
||||
{ ParameterizedAbstractClassController.class, false },
|
||||
{ ParameterizedSubclassOverridesDefaultMappings.class, true }, // CGLIB proxy
|
||||
{ ParameterizedSubclassOverridesDefaultMappings.class, false },
|
||||
|
||||
{ ParameterizedSubclassOverridesDefaultMappings.class, true }, // CGLib proxy
|
||||
{ ParameterizedSubclassOverridesDefaultMappings.class, false },
|
||||
// TODO [SPR-9517] Enable ParameterizedSubclassDoesNotOverrideConcreteImplementationsFromGenericAbstractSuperclass test cases
|
||||
// { ParameterizedSubclassDoesNotOverrideConcreteImplementationsFromGenericAbstractSuperclass.class, true }, // CGLIB proxy
|
||||
// { ParameterizedSubclassDoesNotOverrideConcreteImplementationsFromGenericAbstractSuperclass.class, false },
|
||||
|
||||
// TODO [SPR-9517] Enable ParameterizedSubclassDoesNotOverrideConcreteImplementationsFromGenericAbstractSuperclass test cases
|
||||
// { ParameterizedSubclassDoesNotOverrideConcreteImplementationsFromGenericAbstractSuperclass.class, true }, // CGLib proxy
|
||||
// { ParameterizedSubclassDoesNotOverrideConcreteImplementationsFromGenericAbstractSuperclass.class, false },
|
||||
{ InterfaceController.class, true }, // JDK dynamic proxy
|
||||
{ InterfaceController.class, false },
|
||||
|
||||
{ InterfaceController.class, true }, // JDK dynamic proxy
|
||||
{ InterfaceController.class, false },
|
||||
|
||||
{ ParameterizedInterfaceController.class, false }, // no AOP
|
||||
|
||||
{ SupportClassController.class, true }, // CGLib proxy
|
||||
{ SupportClassController.class, false }
|
||||
{ ParameterizedInterfaceController.class, false }, // no AOP
|
||||
|
||||
{ SupportClassController.class, true }, // CGLIB proxy
|
||||
{ SupportClassController.class, false }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -100,7 +98,8 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
|
||||
private ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver();
|
||||
|
||||
public HandlerMethodAnnotationDetectionTests(final Class<?> controllerType, boolean useAutoProxy) {
|
||||
|
||||
public HandlerMethodAnnotationDetectionTests(Class<?> controllerType, boolean useAutoProxy) {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
context.registerBeanDefinition("controller", new RootBeanDefinition(controllerType));
|
||||
context.registerBeanDefinition("handlerMapping", new RootBeanDefinition(RequestMappingHandlerMapping.class));
|
||||
@@ -120,12 +119,6 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
class TestPointcut extends StaticMethodMatcherPointcut {
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> clazz) {
|
||||
return method.getName().equals("hashCode");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestMappingMethod() throws Exception {
|
||||
@@ -203,9 +196,9 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
public abstract String handleException(Exception exception);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CONTROLLER WITH ABSTRACT CLASS
|
||||
*
|
||||
* <p>All annotations can be on methods in the abstract class except parameter annotations.
|
||||
*/
|
||||
static class AbstractClassController extends MappingAbstractClass {
|
||||
@@ -232,10 +225,10 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
}
|
||||
}
|
||||
|
||||
// SPR-9374
|
||||
|
||||
// SPR-9374
|
||||
@RequestMapping
|
||||
static interface MappingInterface {
|
||||
interface MappingInterface {
|
||||
|
||||
@InitBinder
|
||||
void initBinder(WebDataBinder dataBinder, @RequestParam("datePattern") String thePattern);
|
||||
@@ -252,14 +245,11 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
String handleException(Exception exception);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CONTROLLER WITH INTERFACE
|
||||
*
|
||||
* JDK Dynamic proxy:
|
||||
* All annotations must be on the interface.
|
||||
*
|
||||
* Without AOP:
|
||||
* Annotations can be on interface methods except parameter annotations.
|
||||
* <p>JDK Dynamic proxy: All annotations must be on the interface.
|
||||
* <p>Without AOP: Annotations can be on interface methods except parameter annotations.
|
||||
*/
|
||||
static class InterfaceController implements MappingInterface {
|
||||
|
||||
@@ -304,9 +294,9 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
public abstract String handleException(Exception exception);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CONTROLLER WITH PARAMETERIZED BASE CLASS
|
||||
*
|
||||
* <p>All annotations can be on methods in the abstract class except parameter annotations.
|
||||
*/
|
||||
static class ParameterizedAbstractClassController extends MappingGenericAbstractClass<String, Date, Date> {
|
||||
@@ -333,6 +323,7 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
static abstract class MappedGenericAbstractClassWithConcreteImplementations<A, B, C> {
|
||||
|
||||
@@ -353,6 +344,7 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
public abstract String handleException(Exception exception);
|
||||
}
|
||||
|
||||
|
||||
static class ParameterizedSubclassDoesNotOverrideConcreteImplementationsFromGenericAbstractSuperclass extends
|
||||
MappedGenericAbstractClassWithConcreteImplementations<String, Date, Date> {
|
||||
|
||||
@@ -375,6 +367,7 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
static abstract class GenericAbstractClassDeclaresDefaultMappings<A, B, C> {
|
||||
|
||||
@@ -395,6 +388,7 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
public abstract String handleException(Exception exception);
|
||||
}
|
||||
|
||||
|
||||
static class ParameterizedSubclassOverridesDefaultMappings
|
||||
extends GenericAbstractClassDeclaresDefaultMappings<String, Date, Date> {
|
||||
|
||||
@@ -425,8 +419,9 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping
|
||||
static interface MappingGenericInterface<A, B, C> {
|
||||
interface MappingGenericInterface<A, B, C> {
|
||||
|
||||
@InitBinder
|
||||
void initBinder(WebDataBinder dataBinder, A thePattern);
|
||||
@@ -443,11 +438,10 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
String handleException(Exception exception);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CONTROLLER WITH PARAMETERIZED INTERFACE
|
||||
*
|
||||
* <p>All annotations can be on interface except parameter annotations.
|
||||
*
|
||||
* <p>Cannot be used as JDK dynamic proxy since parameterized interface does not contain type information.
|
||||
*/
|
||||
static class ParameterizedInterfaceController implements MappingGenericInterface<String, Date, Date> {
|
||||
@@ -483,7 +477,6 @@ public class HandlerMethodAnnotationDetectionTests {
|
||||
|
||||
/**
|
||||
* SPR-8248
|
||||
*
|
||||
* <p>Support class contains all annotations. Subclass has type-level @{@link RequestMapping}.
|
||||
*/
|
||||
@Controller
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -70,6 +70,7 @@ public class EnableCachingIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void assertCacheProxying(AnnotationConfigApplicationContext ctx) {
|
||||
FooRepository repo = ctx.getBean(FooRepository.class);
|
||||
|
||||
@@ -89,6 +90,7 @@ public class EnableCachingIntegrationTests {
|
||||
@Configuration
|
||||
@EnableCaching(proxyTargetClass=true)
|
||||
static class ProxyTargetClassCachingConfig {
|
||||
|
||||
@Bean
|
||||
CacheManager mgr() {
|
||||
return new NoOpCacheManager();
|
||||
@@ -98,6 +100,7 @@ public class EnableCachingIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
FooRepository fooRepository() {
|
||||
return new DummyFooRepository();
|
||||
@@ -108,6 +111,7 @@ public class EnableCachingIntegrationTests {
|
||||
@Configuration
|
||||
@EnableCaching(mode=AdviceMode.ASPECTJ)
|
||||
static class AspectJCacheConfig {
|
||||
|
||||
@Bean
|
||||
CacheManager cacheManager() {
|
||||
return new NoOpCacheManager();
|
||||
@@ -116,6 +120,7 @@ public class EnableCachingIntegrationTests {
|
||||
|
||||
|
||||
interface FooRepository {
|
||||
|
||||
List<Object> findAll();
|
||||
}
|
||||
|
||||
@@ -129,4 +134,5 @@ public class EnableCachingIntegrationTests {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,20 +16,14 @@
|
||||
|
||||
package org.springframework.transaction.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
@@ -50,6 +44,9 @@ import org.springframework.tests.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests for the @EnableTransactionManagement annotation.
|
||||
*
|
||||
@@ -169,10 +166,30 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
}
|
||||
|
||||
|
||||
private void assertTxProxying(AnnotationConfigApplicationContext ctx) {
|
||||
FooRepository repo = ctx.getBean(FooRepository.class);
|
||||
|
||||
boolean isTxProxy = false;
|
||||
if (AopUtils.isAopProxy(repo)) {
|
||||
for (Advisor advisor : ((Advised)repo).getAdvisors()) {
|
||||
if (advisor instanceof BeanFactoryTransactionAttributeSourceAdvisor) {
|
||||
isTxProxy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue("FooRepository is not a TX proxy", isTxProxy);
|
||||
|
||||
// trigger a transaction
|
||||
repo.findAll();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@ImportResource("org/springframework/transaction/annotation/enable-caching.xml")
|
||||
static class EnableTxAndCachingConfig {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager() {
|
||||
return new CallCountingTransactionManager();
|
||||
@@ -197,6 +214,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class ImplicitTxManagerConfig {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager() {
|
||||
return new CallCountingTransactionManager();
|
||||
@@ -212,6 +230,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class ExplicitTxManagerConfig implements TransactionManagementConfigurer {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager1() {
|
||||
return new CallCountingTransactionManager();
|
||||
@@ -233,28 +252,11 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
private void assertTxProxying(AnnotationConfigApplicationContext ctx) {
|
||||
FooRepository repo = ctx.getBean(FooRepository.class);
|
||||
|
||||
boolean isTxProxy = false;
|
||||
if (AopUtils.isAopProxy(repo)) {
|
||||
for (Advisor advisor : ((Advised)repo).getAdvisors()) {
|
||||
if (advisor instanceof BeanFactoryTransactionAttributeSourceAdvisor) {
|
||||
isTxProxy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue("FooRepository is not a TX proxy", isTxProxy);
|
||||
|
||||
// trigger a transaction
|
||||
repo.findAll();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class DefaultTxManagerNameConfig {
|
||||
|
||||
@Bean
|
||||
PlatformTransactionManager transactionManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
@@ -265,6 +267,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class CustomTxManagerNameConfig {
|
||||
|
||||
@Bean
|
||||
PlatformTransactionManager txManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
@@ -275,6 +278,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class NonConventionalTxManagerNameConfig {
|
||||
|
||||
@Bean
|
||||
PlatformTransactionManager txManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
@@ -285,6 +289,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass=true)
|
||||
static class ProxyTargetClassTxConfig {
|
||||
|
||||
@Bean
|
||||
PlatformTransactionManager transactionManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
@@ -295,6 +300,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
@Configuration
|
||||
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
|
||||
static class AspectJTxConfig {
|
||||
|
||||
@Bean
|
||||
PlatformTransactionManager transactionManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
@@ -304,6 +310,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
FooRepository fooRepository() {
|
||||
JdbcFooRepository repos = new JdbcFooRepository();
|
||||
@@ -321,6 +328,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
|
||||
|
||||
interface FooRepository {
|
||||
|
||||
List<Object> findAll();
|
||||
}
|
||||
|
||||
@@ -338,6 +346,7 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Repository
|
||||
static class DummyFooRepository implements FooRepository {
|
||||
|
||||
@@ -347,4 +356,5 @@ public class EnableTransactionManagementIntegrationTests {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user