Polishing

This commit is contained in:
Juergen Hoeller
2024-01-09 11:55:04 +01:00
parent 03b6e51225
commit 4d11307b84
5 changed files with 60 additions and 75 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
@@ -23,7 +23,6 @@ import java.util.Map;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutPrimitive;
import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException;
import org.junit.jupiter.api.BeforeEach;
@@ -66,7 +65,7 @@ public class AspectJExpressionPointcutTests {
@BeforeEach
public void setUp() throws NoSuchMethodException {
public void setup() throws NoSuchMethodException {
getAge = TestBean.class.getMethod("getAge");
setAge = TestBean.class.getMethod("setAge", int.class);
setSomeNumber = TestBean.class.getMethod("setSomeNumber", Number.class);
@@ -247,14 +246,13 @@ public class AspectJExpressionPointcutTests {
@Test
public void testInvalidExpression() {
String expression = "execution(void org.springframework.beans.testfixture.beans.TestBean.setSomeNumber(Number) && args(Double)";
assertThatIllegalArgumentException().isThrownBy(
getPointcut(expression)::getClassFilter); // call to getClassFilter forces resolution
assertThatIllegalArgumentException().isThrownBy(getPointcut(expression)::getClassFilter); // call to getClassFilter forces resolution
}
private TestBean getAdvisedProxy(String pointcutExpression, CallCountingInterceptor interceptor) {
TestBean target = new TestBean();
Pointcut pointcut = getPointcut(pointcutExpression);
AspectJExpressionPointcut pointcut = getPointcut(pointcutExpression);
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setAdvice(interceptor);
@@ -278,40 +276,31 @@ public class AspectJExpressionPointcutTests {
@Test
public void testWithUnsupportedPointcutPrimitive() {
String expression = "call(int org.springframework.beans.testfixture.beans.TestBean.getAge())";
assertThatExceptionOfType(UnsupportedPointcutPrimitiveException.class).isThrownBy(() ->
getPointcut(expression).getClassFilter()) // call to getClassFilter forces resolution...
.satisfies(ex -> assertThat(ex.getUnsupportedPrimitive()).isEqualTo(PointcutPrimitive.CALL));
assertThatExceptionOfType(UnsupportedPointcutPrimitiveException.class)
.isThrownBy(() -> getPointcut(expression).getClassFilter()) // call to getClassFilter forces resolution...
.satisfies(ex -> assertThat(ex.getUnsupportedPrimitive()).isEqualTo(PointcutPrimitive.CALL));
}
@Test
public void testAndSubstitution() {
Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
assertThat(expr.getPointcutExpression()).isEqualTo("execution(* *(..)) && args(String)");
AspectJExpressionPointcut pc = getPointcut("execution(* *(..)) and args(String)");
String expr = pc.getPointcutExpression().getPointcutExpression();
assertThat(expr).isEqualTo("execution(* *(..)) && args(String)");
}
@Test
public void testMultipleAndSubstitutions() {
Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
assertThat(expr.getPointcutExpression()).isEqualTo("execution(* *(..)) && args(String) && this(Object)");
AspectJExpressionPointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
String expr = pc.getPointcutExpression().getPointcutExpression();
assertThat(expr).isEqualTo("execution(* *(..)) && args(String) && this(Object)");
}
private Pointcut getPointcut(String expression) {
private AspectJExpressionPointcut getPointcut(String expression) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(expression);
return pointcut;
}
public static class OtherIOther implements IOther {
@Override
public void absquatulate() {
// Empty
}
}
@Test
public void testMatchGenericArgument() {
String expression = "execution(* set*(java.util.List<org.springframework.beans.testfixture.beans.TestBean>) )";
@@ -531,6 +520,15 @@ public class AspectJExpressionPointcutTests {
}
public static class OtherIOther implements IOther {
@Override
public void absquatulate() {
// Empty
}
}
public static class HasGeneric {
public void setFriends(List<TestBean> friends) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
@@ -604,7 +604,6 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
@@ -220,16 +220,16 @@ class AspectJAutoProxyCreatorTests {
try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(configClass)) {
testBean1 = context.getBean(TestBean.class);
assertThat(AopUtils.isCglibProxy(testBean1)).as("CGLIB proxy").isTrue();
assertThat(testBean1.getClass().getInterfaces())
.containsExactlyInAnyOrder(Factory.class, SpringProxy.class, Advised.class);
assertThat(testBean1.getClass().getInterfaces()).containsExactlyInAnyOrder(
Factory.class, SpringProxy.class, Advised.class);
}
// Round #2
try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(configClass)) {
testBean2 = context.getBean(TestBean.class);
assertThat(AopUtils.isCglibProxy(testBean2)).as("CGLIB proxy").isTrue();
assertThat(testBean2.getClass().getInterfaces())
.containsExactlyInAnyOrder(Factory.class, SpringProxy.class, Advised.class);
assertThat(testBean2.getClass().getInterfaces()).containsExactlyInAnyOrder(
Factory.class, SpringProxy.class, Advised.class);
}
assertThat(testBean1.getClass()).isSameAs(testBean2.getClass());
@@ -344,8 +344,8 @@ class AspectJAutoProxyCreatorTests {
Supplier<String> supplier = context.getBean(Supplier.class);
assertThat(AopUtils.isAopProxy(supplier)).as("AOP proxy").isTrue();
assertThat(AopUtils.isJdkDynamicProxy(supplier)).as("JDK Dynamic proxy").isTrue();
assertThat(supplier.getClass().getInterfaces())
.containsExactlyInAnyOrder(Supplier.class, SpringProxy.class, Advised.class, DecoratingProxy.class);
assertThat(supplier.getClass().getInterfaces()).containsExactlyInAnyOrder(
Supplier.class, SpringProxy.class, Advised.class, DecoratingProxy.class);
assertThat(supplier.get()).isEqualTo("advised: lambda");
}
}
@@ -357,26 +357,14 @@ class AspectJAutoProxyCreatorTests {
MessageGenerator messageGenerator = context.getBean(MessageGenerator.class);
assertThat(AopUtils.isAopProxy(messageGenerator)).as("AOP proxy").isTrue();
assertThat(AopUtils.isJdkDynamicProxy(messageGenerator)).as("JDK Dynamic proxy").isTrue();
assertThat(messageGenerator.getClass().getInterfaces())
.containsExactlyInAnyOrder(MessageGenerator.class, Mixin.class, SpringProxy.class, Advised.class, DecoratingProxy.class);
assertThat(messageGenerator.getClass().getInterfaces()).containsExactlyInAnyOrder(
MessageGenerator.class, Mixin.class, SpringProxy.class, Advised.class, DecoratingProxy.class);
assertThat(messageGenerator.generateMessage()).isEqualTo("mixin: lambda");
}
}
/**
* Returns a new {@link ClassPathXmlApplicationContext} for the file ending in <var>fileSuffix</var>.
*/
private ClassPathXmlApplicationContext newContext(String fileSuffix) {
return new ClassPathXmlApplicationContext(qName(fileSuffix), getClass());
}
/**
* Returns the relatively qualified name for <var>fileSuffix</var>.
* e.g. for a fileSuffix='foo.xml', this method will return
* 'AspectJAutoProxyCreatorTests-foo.xml'
*/
private String qName(String fileSuffix) {
return String.format("%s-%s", getClass().getSimpleName(), fileSuffix);
return new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-" + fileSuffix, getClass());
}
}
@@ -416,7 +404,6 @@ class DummyAspectWithParameter {
public Object test(ProceedingJoinPoint pjp, int age) throws Throwable {
return pjp.proceed();
}
}
class DummyFactoryBean implements FactoryBean<Object> {
@@ -435,7 +422,6 @@ class DummyFactoryBean implements FactoryBean<Object> {
public boolean isSingleton() {
throw new UnsupportedOperationException();
}
}
@Aspect
@@ -591,7 +577,6 @@ class UnreliableBean {
}
return this.calls;
}
}
@SuppressWarnings("serial")
@@ -607,7 +592,6 @@ class TestBeanAdvisor extends StaticMethodMatcherPointcutAdvisor {
public boolean matches(Method method, @Nullable Class<?> targetClass) {
return ITestBean.class.isAssignableFrom(targetClass);
}
}
abstract class AbstractProxyTargetClassConfig {
@@ -661,6 +645,7 @@ class PerTargetProxyTargetClassTrueConfig {
@FunctionalInterface
interface MessageGenerator {
String generateMessage();
}
@@ -678,7 +663,6 @@ class MixinIntroductionInterceptor implements IntroductionInterceptor {
public boolean implementsInterface(Class<?> intf) {
return Mixin.class.isAssignableFrom(intf);
}
}
@SuppressWarnings("serial")
@@ -708,7 +692,6 @@ class MixinAdvisor extends AbstractPointcutAdvisor implements IntroductionAdviso
public void validateInterfaces() {
/* no-op */
}
}
abstract class AbstractMixinConfig {
@@ -722,7 +705,6 @@ abstract class AbstractMixinConfig {
MixinAdvisor mixinAdvisor() {
return new MixinAdvisor();
}
}
@Configuration(proxyBeanMethods = false)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
@@ -1571,7 +1571,9 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
return result;
}
private void storeGeneratedKeys(KeyHolder generatedKeyHolder, PreparedStatement ps, int rowsExpected) throws SQLException {
private void storeGeneratedKeys(KeyHolder generatedKeyHolder, PreparedStatement ps, int rowsExpected)
throws SQLException {
List<Map<String, Object>> generatedKeys = generatedKeyHolder.getKeyList();
ResultSet keys = ps.getGeneratedKeys();
if (keys != null) {
@@ -1586,7 +1588,8 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
}
}
private PreparedStatementCallback<int[]> getPreparedStatementCallback(BatchPreparedStatementSetter pss, @Nullable KeyHolder generatedKeyHolder) {
private PreparedStatementCallback<int[]> getPreparedStatementCallback(BatchPreparedStatementSetter pss,
@Nullable KeyHolder generatedKeyHolder) {
return ps -> {
try {
int batchSize = pss.getBatchSize();
@@ -1665,8 +1668,10 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
case "isClosed" -> false;
// Handle getTargetConnection method: return underlying Connection.
case "getTargetConnection" -> this.target;
case "unwrap" -> (((Class<?>) args[0]).isInstance(proxy) ? proxy : this.target.unwrap((Class<?>) args[0]));
case "isWrapperFor" -> (((Class<?>) args[0]).isInstance(proxy) || this.target.isWrapperFor((Class<?>) args[0]));
case "unwrap" ->
(((Class<?>) args[0]).isInstance(proxy) ? proxy : this.target.unwrap((Class<?>) args[0]));
case "isWrapperFor" ->
(((Class<?>) args[0]).isInstance(proxy) || this.target.isWrapperFor((Class<?>) args[0]));
default -> {
try {
// Invoke method on target Connection.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
@@ -87,8 +87,8 @@ class SQLErrorCodeSQLExceptionTranslatorTests {
SQLException dupKeyEx = new SQLException("", "", 10);
DataAccessException dataAccessException = translator.translate("task", "SQL", dupKeyEx);
assertThat(dataAccessException)
.isInstanceOf(DataIntegrityViolationException.class)
.hasCause(dupKeyEx);
.isInstanceOf(DataIntegrityViolationException.class)
.hasCause(dupKeyEx);
// Test fallback. We assume that no database will ever return this error code,
// but 07xxx will be bad grammar picked up by the fallback SQLState translator
@@ -102,8 +102,8 @@ class SQLErrorCodeSQLExceptionTranslatorTests {
SQLException sqlException = new SQLException("", "", errorCode);
DataAccessException dataAccessException = this.translator.translate("", "", sqlException);
assertThat(dataAccessException)
.isInstanceOf(expectedType)
.hasCause(sqlException);
.isInstanceOf(expectedType)
.hasCause(sqlException);
}
@Test
@@ -122,8 +122,8 @@ class SQLErrorCodeSQLExceptionTranslatorTests {
DataTruncation dataTruncation = new DataTruncation(1, true, true, 1, 1, dataAccessEx);
DataAccessException dataAccessException = translator.translate("task", "SQL", dataTruncation);
assertThat(dataAccessException)
.isInstanceOf(DataAccessResourceFailureException.class)
.hasCause(dataTruncation);
.isInstanceOf(DataAccessResourceFailureException.class)
.hasCause(dataTruncation);
}
@Test
@@ -154,8 +154,8 @@ class SQLErrorCodeSQLExceptionTranslatorTests {
// Shouldn't custom translate this
DataAccessException dataAccessException = translator.translate(TASK, SQL, integrityViolationEx);
assertThat(dataAccessException)
.isInstanceOf(DataIntegrityViolationException.class)
.hasCause(integrityViolationEx);
.isInstanceOf(DataIntegrityViolationException.class)
.hasCause(integrityViolationEx);
}
@Test
@@ -177,15 +177,15 @@ class SQLErrorCodeSQLExceptionTranslatorTests {
SQLException badSqlEx = new SQLException("", "", 1);
DataAccessException dataAccessException = translator.translate(TASK, SQL, badSqlEx);
assertThat(dataAccessException)
.isInstanceOf(CustomErrorCodeException.class)
.hasCause(badSqlEx);
.isInstanceOf(CustomErrorCodeException.class)
.hasCause(badSqlEx);
// Shouldn't custom translate this
SQLException invResEx = new SQLException("", "", 3);
dataAccessException = translator.translate(TASK, SQL, invResEx);
assertThat(dataAccessException)
.isInstanceOf(DataIntegrityViolationException.class)
.hasCause(invResEx);
.isInstanceOf(DataIntegrityViolationException.class)
.hasCause(invResEx);
// Shouldn't custom translate this - invalid class
assertThatIllegalArgumentException().isThrownBy(() -> customTranslation.setExceptionClass(String.class));
@@ -210,7 +210,8 @@ class SQLErrorCodeSQLExceptionTranslatorTests {
reset(dataSource);
given(dataSource.getConnection()).willReturn(connection);
assertThat(translator.translate("test", null, duplicateKeyException)).isInstanceOf(DuplicateKeyException.class);
assertThat(translator.translate("test", null, duplicateKeyException))
.isInstanceOf(DuplicateKeyException.class);
verify(connection).close();
}