Browse Source

Polishing (aligned with 6.1.x)

pull/33048/head
Juergen Hoeller 2 years ago
parent
commit
94097fb112
  1. 10
      spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
  2. 2
      spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
  3. 98
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanEarlyDeductionTests.java
  4. 59
      spring-jdbc/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java
  5. 6
      spring-tx/src/main/java/org/springframework/transaction/interceptor/DefaultTransactionAttribute.java
  6. 10
      spring-tx/src/main/java/org/springframework/transaction/reactive/AbstractReactiveTransactionManager.java
  7. 7
      spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java
  8. 6
      spring-tx/src/main/java/org/springframework/transaction/support/DefaultTransactionDefinition.java

10
spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -818,11 +818,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
/** /**
* This implementation attempts to query the FactoryBean's generic parameter metadata * This implementation attempts to query the FactoryBean's generic parameter metadata
* if present to determine the object type. If not present, i.e. the FactoryBean is * if present to determine the object type. If not present, i.e. the FactoryBean is
* declared as a raw type, checks the FactoryBean's {@code getObjectType} method * declared as a raw type, it checks the FactoryBean's {@code getObjectType} method
* on a plain instance of the FactoryBean, without bean properties applied yet. * on a plain instance of the FactoryBean, without bean properties applied yet.
* If this doesn't return a type yet, and {@code allowInit} is {@code true} a * If this doesn't return a type yet and {@code allowInit} is {@code true}, full
* full creation of the FactoryBean is used as fallback (through delegation to the * creation of the FactoryBean is attempted as fallback (through delegation to the
* superclass's implementation). * superclass implementation).
* <p>The shortcut check for a FactoryBean is only applied in case of a singleton * <p>The shortcut check for a FactoryBean is only applied in case of a singleton
* FactoryBean. If the FactoryBean instance itself is not kept as singleton, * FactoryBean. If the FactoryBean instance itself is not kept as singleton,
* it will be fully created to check the type of its exposed object. * it will be fully created to check the type of its exposed object.

2
spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

@ -1649,7 +1649,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* already. The implementation is allowed to instantiate the target factory bean if * already. The implementation is allowed to instantiate the target factory bean if
* {@code allowInit} is {@code true} and the type cannot be determined another way; * {@code allowInit} is {@code true} and the type cannot be determined another way;
* otherwise it is restricted to introspecting signatures and related metadata. * otherwise it is restricted to introspecting signatures and related metadata.
* <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} if set on the bean definition * <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} is set on the bean definition
* and {@code allowInit} is {@code true}, the default implementation will create * and {@code allowInit} is {@code true}, the default implementation will create
* the FactoryBean via {@code getBean} to call its {@code getObjectType} method. * the FactoryBean via {@code getBean} to call its {@code getObjectType} method.
* Subclasses are encouraged to optimize this, typically by inspecting the generic * Subclasses are encouraged to optimize this, typically by inspecting the generic

98
spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanBeanEarlyDeductionTests.java → spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanEarlyDeductionTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,7 +29,9 @@ import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -39,51 +41,62 @@ import static org.assertj.core.api.Assertions.assertThat;
* {@link FactoryBean FactoryBeans} defined in the configuration. * {@link FactoryBean FactoryBeans} defined in the configuration.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Juergen Hoeller
*/ */
public class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { class ConfigurationWithFactoryBeanEarlyDeductionTests {
@Test @Test
public void preFreezeDirect() { void preFreezeDirect() {
assertPreFreeze(DirectConfiguration.class); assertPreFreeze(DirectConfiguration.class);
} }
@Test @Test
public void postFreezeDirect() { void postFreezeDirect() {
assertPostFreeze(DirectConfiguration.class); assertPostFreeze(DirectConfiguration.class);
} }
@Test @Test
public void preFreezeGenericMethod() { void preFreezeGenericMethod() {
assertPreFreeze(GenericMethodConfiguration.class); assertPreFreeze(GenericMethodConfiguration.class);
} }
@Test @Test
public void postFreezeGenericMethod() { void postFreezeGenericMethod() {
assertPostFreeze(GenericMethodConfiguration.class); assertPostFreeze(GenericMethodConfiguration.class);
} }
@Test @Test
public void preFreezeGenericClass() { void preFreezeGenericClass() {
assertPreFreeze(GenericClassConfiguration.class); assertPreFreeze(GenericClassConfiguration.class);
} }
@Test @Test
public void postFreezeGenericClass() { void postFreezeGenericClass() {
assertPostFreeze(GenericClassConfiguration.class); assertPostFreeze(GenericClassConfiguration.class);
} }
@Test @Test
public void preFreezeAttribute() { void preFreezeAttribute() {
assertPreFreeze(AttributeClassConfiguration.class); assertPreFreeze(AttributeClassConfiguration.class);
} }
@Test @Test
public void postFreezeAttribute() { void postFreezeAttribute() {
assertPostFreeze(AttributeClassConfiguration.class); assertPostFreeze(AttributeClassConfiguration.class);
} }
@Test @Test
public void preFreezeUnresolvedGenericFactoryBean() { void preFreezeTargetType() {
assertPreFreeze(TargetTypeConfiguration.class);
}
@Test
void postFreezeTargetType() {
assertPostFreeze(TargetTypeConfiguration.class);
}
@Test
void preFreezeUnresolvedGenericFactoryBean() {
// Covers the case where a @Configuration is picked up via component scanning // Covers the case where a @Configuration is picked up via component scanning
// and its bean definition only has a String bean class. In such cases // and its bean definition only has a String bean class. In such cases
// beanDefinition.hasBeanClass() returns false so we need to actually // beanDefinition.hasBeanClass() returns false so we need to actually
@ -105,14 +118,13 @@ public class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
} }
} }
private void assertPostFreeze(Class<?> configurationClass) { private void assertPostFreeze(Class<?> configurationClass) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configurationClass);
configurationClass);
assertContainsMyBeanName(context); assertContainsMyBeanName(context);
} }
private void assertPreFreeze(Class<?> configurationClass, private void assertPreFreeze(Class<?> configurationClass, BeanFactoryPostProcessor... postProcessors) {
BeanFactoryPostProcessor... postProcessors) {
NameCollectingBeanFactoryPostProcessor postProcessor = new NameCollectingBeanFactoryPostProcessor(); NameCollectingBeanFactoryPostProcessor postProcessor = new NameCollectingBeanFactoryPostProcessor();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
try (context) { try (context) {
@ -132,41 +144,38 @@ public class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
assertThat(names).containsExactly("myBean"); assertThat(names).containsExactly("myBean");
} }
private static class NameCollectingBeanFactoryPostProcessor
implements BeanFactoryPostProcessor { private static class NameCollectingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private String[] names; private String[] names;
@Override @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
throws BeansException { ResolvableType typeToMatch = ResolvableType.forClassWithGenerics(MyBean.class, String.class);
this.names = beanFactory.getBeanNamesForType(MyBean.class, true, false); this.names = beanFactory.getBeanNamesForType(typeToMatch, true, false);
} }
public String[] getNames() { public String[] getNames() {
return this.names; return this.names;
} }
} }
@Configuration @Configuration
static class DirectConfiguration { static class DirectConfiguration {
@Bean @Bean
MyBean myBean() { MyBean<String> myBean() {
return new MyBean(); return new MyBean<>();
} }
} }
@Configuration @Configuration
static class GenericMethodConfiguration { static class GenericMethodConfiguration {
@Bean @Bean
FactoryBean<MyBean> myBean() { FactoryBean<MyBean<String>> myBean() {
return new TestFactoryBean<>(new MyBean()); return new TestFactoryBean<>(new MyBean<>());
} }
} }
@Configuration @Configuration
@ -176,13 +185,11 @@ public class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
MyFactoryBean myBean() { MyFactoryBean myBean() {
return new MyFactoryBean(); return new MyFactoryBean();
} }
} }
@Configuration @Configuration
@Import(AttributeClassRegistrar.class) @Import(AttributeClassRegistrar.class)
static class AttributeClassConfiguration { static class AttributeClassConfiguration {
} }
static class AttributeClassRegistrar implements ImportBeanDefinitionRegistrar { static class AttributeClassRegistrar implements ImportBeanDefinitionRegistrar {
@ -191,16 +198,32 @@ public class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition( BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(
RawWithAbstractObjectTypeFactoryBean.class).getBeanDefinition(); RawWithAbstractObjectTypeFactoryBean.class).getBeanDefinition();
definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, MyBean.class); definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE,
ResolvableType.forClassWithGenerics(MyBean.class, String.class));
registry.registerBeanDefinition("myBean", definition); registry.registerBeanDefinition("myBean", definition);
} }
}
@Configuration
@Import(TargetTypeRegistrar.class)
static class TargetTypeConfiguration {
}
static class TargetTypeRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition definition = new RootBeanDefinition(RawWithAbstractObjectTypeFactoryBean.class);
definition.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class,
ResolvableType.forClassWithGenerics(MyBean.class, String.class)));
registry.registerBeanDefinition("myBean", definition);
}
} }
abstract static class AbstractMyBean { abstract static class AbstractMyBean {
} }
static class MyBean extends AbstractMyBean { static class MyBean<T> extends AbstractMyBean {
} }
static class TestFactoryBean<T> implements FactoryBean<T> { static class TestFactoryBean<T> implements FactoryBean<T> {
@ -212,7 +235,7 @@ public class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
} }
@Override @Override
public T getObject() throws Exception { public T getObject() {
return this.instance; return this.instance;
} }
@ -220,31 +243,26 @@ public class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
public Class<?> getObjectType() { public Class<?> getObjectType() {
return this.instance.getClass(); return this.instance.getClass();
} }
} }
static class MyFactoryBean extends TestFactoryBean<MyBean> { static class MyFactoryBean extends TestFactoryBean<MyBean<String>> {
public MyFactoryBean() { public MyFactoryBean() {
super(new MyBean()); super(new MyBean<>());
} }
} }
static class RawWithAbstractObjectTypeFactoryBean implements FactoryBean<Object> { static class RawWithAbstractObjectTypeFactoryBean implements FactoryBean<Object> {
private final Object object = new MyBean();
@Override @Override
public Object getObject() throws Exception { public Object getObject() throws Exception {
return object; throw new IllegalStateException();
} }
@Override @Override
public Class<?> getObjectType() { public Class<?> getObjectType() {
return MyBean.class; return MyBean.class;
} }
} }
} }

59
spring-jdbc/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -37,167 +37,168 @@ import static org.mockito.Mockito.mock;
/** /**
* @author Thomas Risberg * @author Thomas Risberg
*/ */
public class ResultSetWrappingRowSetTests { class ResultSetWrappingRowSetTests {
private ResultSet resultSet = mock(); private final ResultSet resultSet = mock();
private ResultSetWrappingSqlRowSet rowSet = new ResultSetWrappingSqlRowSet(resultSet); private final ResultSetWrappingSqlRowSet rowSet = new ResultSetWrappingSqlRowSet(resultSet);
@Test @Test
public void testGetBigDecimalInt() throws Exception { void testGetBigDecimalInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getBigDecimal", int.class); Method rset = ResultSet.class.getDeclaredMethod("getBigDecimal", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBigDecimal", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBigDecimal", int.class);
doTest(rset, rowset, 1, BigDecimal.ONE); doTest(rset, rowset, 1, BigDecimal.ONE);
} }
@Test @Test
public void testGetBigDecimalString() throws Exception { void testGetBigDecimalString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getBigDecimal", int.class); Method rset = ResultSet.class.getDeclaredMethod("getBigDecimal", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBigDecimal", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBigDecimal", String.class);
doTest(rset, rowset, "test", BigDecimal.ONE); doTest(rset, rowset, "test", BigDecimal.ONE);
} }
@Test @Test
public void testGetStringInt() throws Exception { void testGetStringInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getString", int.class); Method rset = ResultSet.class.getDeclaredMethod("getString", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getString", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getString", int.class);
doTest(rset, rowset, 1, "test"); doTest(rset, rowset, 1, "test");
} }
@Test @Test
public void testGetStringString() throws Exception { void testGetStringString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getString", int.class); Method rset = ResultSet.class.getDeclaredMethod("getString", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getString", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getString", String.class);
doTest(rset, rowset, "test", "test"); doTest(rset, rowset, "test", "test");
} }
@Test @Test
public void testGetTimestampInt() throws Exception { void testGetTimestampInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getTimestamp", int.class); Method rset = ResultSet.class.getDeclaredMethod("getTimestamp", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTimestamp", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTimestamp", int.class);
doTest(rset, rowset, 1, new Timestamp(1234L)); doTest(rset, rowset, 1, new Timestamp(1234L));
} }
@Test @Test
public void testGetTimestampString() throws Exception { void testGetTimestampString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getTimestamp", int.class); Method rset = ResultSet.class.getDeclaredMethod("getTimestamp", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTimestamp", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTimestamp", String.class);
doTest(rset, rowset, "test", new Timestamp(1234L)); doTest(rset, rowset, "test", new Timestamp(1234L));
} }
@Test @Test
public void testGetDateInt() throws Exception { void testGetDateInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getDate", int.class); Method rset = ResultSet.class.getDeclaredMethod("getDate", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDate", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDate", int.class);
doTest(rset, rowset, 1, new Date(1234L)); doTest(rset, rowset, 1, new Date(1234L));
} }
@Test @Test
public void testGetDateString() throws Exception { void testGetDateString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getDate", int.class); Method rset = ResultSet.class.getDeclaredMethod("getDate", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDate", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDate", String.class);
doTest(rset, rowset, "test", new Date(1234L)); doTest(rset, rowset, "test", new Date(1234L));
} }
@Test @Test
public void testGetTimeInt() throws Exception { void testGetTimeInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getTime", int.class); Method rset = ResultSet.class.getDeclaredMethod("getTime", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTime", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTime", int.class);
doTest(rset, rowset, 1, new Time(1234L)); doTest(rset, rowset, 1, new Time(1234L));
} }
@Test @Test
public void testGetTimeString() throws Exception { void testGetTimeString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getTime", int.class); Method rset = ResultSet.class.getDeclaredMethod("getTime", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTime", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTime", String.class);
doTest(rset, rowset, "test", new Time(1234L)); doTest(rset, rowset, "test", new Time(1234L));
} }
@Test @Test
public void testGetObjectInt() throws Exception { void testGetObjectInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getObject", int.class); Method rset = ResultSet.class.getDeclaredMethod("getObject", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getObject", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getObject", int.class);
doTest(rset, rowset, 1, new Object()); doTest(rset, rowset, 1, new Object());
} }
@Test @Test
public void testGetObjectString() throws Exception { void testGetObjectString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getObject", int.class); Method rset = ResultSet.class.getDeclaredMethod("getObject", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getObject", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getObject", String.class);
doTest(rset, rowset, "test", new Object()); doTest(rset, rowset, "test", new Object());
} }
@Test @Test
public void testGetIntInt() throws Exception { void testGetIntInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getInt", int.class); Method rset = ResultSet.class.getDeclaredMethod("getInt", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getInt", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getInt", int.class);
doTest(rset, rowset, 1, 1); doTest(rset, rowset, 1, 1);
} }
@Test @Test
public void testGetIntString() throws Exception { void testGetIntString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getInt", int.class); Method rset = ResultSet.class.getDeclaredMethod("getInt", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getInt", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getInt", String.class);
doTest(rset, rowset, "test", 1); doTest(rset, rowset, "test", 1);
} }
@Test @Test
public void testGetFloatInt() throws Exception { void testGetFloatInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getFloat", int.class); Method rset = ResultSet.class.getDeclaredMethod("getFloat", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getFloat", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getFloat", int.class);
doTest(rset, rowset, 1, 1.0f); doTest(rset, rowset, 1, 1.0f);
} }
@Test @Test
public void testGetFloatString() throws Exception { void testGetFloatString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getFloat", int.class); Method rset = ResultSet.class.getDeclaredMethod("getFloat", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getFloat", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getFloat", String.class);
doTest(rset, rowset, "test", 1.0f); doTest(rset, rowset, "test", 1.0f);
} }
@Test @Test
public void testGetDoubleInt() throws Exception { void testGetDoubleInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getDouble", int.class); Method rset = ResultSet.class.getDeclaredMethod("getDouble", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDouble", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDouble", int.class);
doTest(rset, rowset, 1, 1.0d); doTest(rset, rowset, 1, 1.0d);
} }
@Test @Test
public void testGetDoubleString() throws Exception { void testGetDoubleString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getDouble", int.class); Method rset = ResultSet.class.getDeclaredMethod("getDouble", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDouble", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDouble", String.class);
doTest(rset, rowset, "test", 1.0d); doTest(rset, rowset, "test", 1.0d);
} }
@Test @Test
public void testGetLongInt() throws Exception { void testGetLongInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getLong", int.class); Method rset = ResultSet.class.getDeclaredMethod("getLong", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getLong", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getLong", int.class);
doTest(rset, rowset, 1, 1L); doTest(rset, rowset, 1, 1L);
} }
@Test @Test
public void testGetLongString() throws Exception { void testGetLongString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getLong", int.class); Method rset = ResultSet.class.getDeclaredMethod("getLong", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getLong", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getLong", String.class);
doTest(rset, rowset, "test", 1L); doTest(rset, rowset, "test", 1L);
} }
@Test @Test
public void testGetBooleanInt() throws Exception { void testGetBooleanInt() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getBoolean", int.class); Method rset = ResultSet.class.getDeclaredMethod("getBoolean", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBoolean", int.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBoolean", int.class);
doTest(rset, rowset, 1, true); doTest(rset, rowset, 1, true);
} }
@Test @Test
public void testGetBooleanString() throws Exception { void testGetBooleanString() throws Exception {
Method rset = ResultSet.class.getDeclaredMethod("getBoolean", int.class); Method rset = ResultSet.class.getDeclaredMethod("getBoolean", int.class);
Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBoolean", String.class); Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBoolean", String.class);
doTest(rset, rowset, "test", true); doTest(rset, rowset, "test", true);
} }
private void doTest(Method rsetMethod, Method rowsetMethod, Object arg, Object ret) throws Exception { private void doTest(Method rsetMethod, Method rowsetMethod, Object arg, Object ret) throws Exception {
if (arg instanceof String) { if (arg instanceof String) {
given(resultSet.findColumn((String) arg)).willReturn(1); given(resultSet.findColumn((String) arg)).willReturn(1);
@ -207,9 +208,9 @@ public class ResultSetWrappingRowSetTests {
given(rsetMethod.invoke(resultSet, arg)).willReturn(ret).willThrow(new SQLException("test")); given(rsetMethod.invoke(resultSet, arg)).willReturn(ret).willThrow(new SQLException("test"));
} }
rowsetMethod.invoke(rowSet, arg); rowsetMethod.invoke(rowSet, arg);
assertThatExceptionOfType(InvocationTargetException.class).isThrownBy(() -> assertThatExceptionOfType(InvocationTargetException.class)
rowsetMethod.invoke(rowSet, arg)). .isThrownBy(() -> rowsetMethod.invoke(rowSet, arg))
satisfies(ex -> assertThat(ex.getTargetException()).isExactlyInstanceOf(InvalidResultSetAccessException.class)); .satisfies(ex -> assertThat(ex.getTargetException()).isExactlyInstanceOf(InvalidResultSetAccessException.class));
} }
} }

6
spring-tx/src/main/java/org/springframework/transaction/interceptor/DefaultTransactionAttribute.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -51,7 +51,7 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im
/** /**
* Create a new DefaultTransactionAttribute, with default settings. * Create a new {@code DefaultTransactionAttribute} with default settings.
* Can be modified through bean property setters. * Can be modified through bean property setters.
* @see #setPropagationBehavior * @see #setPropagationBehavior
* @see #setIsolationLevel * @see #setIsolationLevel
@ -76,7 +76,7 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im
} }
/** /**
* Create a new DefaultTransactionAttribute with the given * Create a new {@code DefaultTransactionAttribute} with the given
* propagation behavior. Can be modified through bean property setters. * propagation behavior. Can be modified through bean property setters.
* @param propagationBehavior one of the propagation constants in the * @param propagationBehavior one of the propagation constants in the
* TransactionDefinition interface * TransactionDefinition interface

10
spring-tx/src/main/java/org/springframework/transaction/reactive/AbstractReactiveTransactionManager.java

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -210,11 +210,13 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
prepareSynchronization(synchronizationManager, status, definition)).thenReturn(status); prepareSynchronization(synchronizationManager, status, definition)).thenReturn(status);
} }
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. // PROPAGATION_REQUIRED, PROPAGATION_SUPPORTS, PROPAGATION_MANDATORY:
// regular participation in existing transaction.
if (debugEnabled) { if (debugEnabled) {
logger.debug("Participating in existing transaction"); logger.debug("Participating in existing transaction");
} }
return Mono.just(prepareReactiveTransaction(synchronizationManager, definition, transaction, false, debugEnabled, null)); return Mono.just(prepareReactiveTransaction(
synchronizationManager, definition, transaction, false, debugEnabled, null));
} }
/** /**
@ -330,7 +332,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
if (resourcesHolder != null) { if (resourcesHolder != null) {
Object suspendedResources = resourcesHolder.suspendedResources; Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) { if (suspendedResources != null) {
resume = doResume(synchronizationManager, transaction, suspendedResources); resume = doResume(synchronizationManager, transaction, suspendedResources);
} }
List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations; List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
if (suspendedSynchronizations != null) { if (suspendedSynchronizations != null) {

7
spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -451,7 +451,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
if (useSavepointForNestedTransaction()) { if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction, // Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus. // through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization. // Usually uses JDBC savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status = DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint(); status.createAndHoldSavepoint();
@ -465,7 +465,8 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
} }
} }
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. // PROPAGATION_REQUIRED, PROPAGATION_SUPPORTS, PROPAGATION_MANDATORY:
// regular participation in existing transaction.
if (debugEnabled) { if (debugEnabled) {
logger.debug("Participating in existing transaction"); logger.debug("Participating in existing transaction");
} }

6
spring-tx/src/main/java/org/springframework/transaction/support/DefaultTransactionDefinition.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -65,7 +65,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
/** /**
* Create a new DefaultTransactionDefinition, with default settings. * Create a new {@code DefaultTransactionDefinition} with default settings.
* Can be modified through bean property setters. * Can be modified through bean property setters.
* @see #setPropagationBehavior * @see #setPropagationBehavior
* @see #setIsolationLevel * @see #setIsolationLevel
@ -93,7 +93,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
} }
/** /**
* Create a new DefaultTransactionDefinition with the given * Create a new {@code DefaultTransactionDefinition} with the given
* propagation behavior. Can be modified through bean property setters. * propagation behavior. Can be modified through bean property setters.
* @param propagationBehavior one of the propagation constants in the * @param propagationBehavior one of the propagation constants in the
* TransactionDefinition interface * TransactionDefinition interface

Loading…
Cancel
Save