Browse Source

Merge branch '6.1.x'

pull/32674/head
Juergen Hoeller 2 years ago
parent
commit
e42c5ca52b
  1. 8
      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. 78
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanEarlyDeductionTests.java
  4. 11
      spring-jdbc/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java
  5. 4
      spring-tx/src/main/java/org/springframework/transaction/interceptor/DefaultTransactionAttribute.java
  6. 8
      spring-tx/src/main/java/org/springframework/transaction/reactive/AbstractReactiveTransactionManager.java
  7. 3
      spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java
  8. 6
      spring-tx/src/main/java/org/springframework/transaction/support/DefaultTransactionDefinition.java

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

@ -823,11 +823,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -823,11 +823,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
/**
* 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
* 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.
* If this doesn't return a type yet, and {@code allowInit} is {@code true} a
* full creation of the FactoryBean is used as fallback (through delegation to the
* superclass's implementation).
* If this doesn't return a type yet and {@code allowInit} is {@code true}, full
* creation of the FactoryBean is attempted as fallback (through delegation to the
* superclass implementation).
* <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,
* 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

@ -1682,7 +1682,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp @@ -1682,7 +1682,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* 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;
* 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
* the FactoryBean via {@code getBean} to call its {@code getObjectType} method.
* Subclasses are encouraged to optimize this, typically by inspecting the generic

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

@ -29,7 +29,9 @@ import org.springframework.beans.factory.support.AbstractBeanFactory; @@ -29,7 +29,9 @@ import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.core.type.AnnotationMetadata;
import static org.assertj.core.api.Assertions.assertThat;
@ -39,8 +41,9 @@ import static org.assertj.core.api.Assertions.assertThat; @@ -39,8 +41,9 @@ import static org.assertj.core.api.Assertions.assertThat;
* {@link FactoryBean FactoryBeans} defined in the configuration.
*
* @author Phillip Webb
* @author Juergen Hoeller
*/
class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
class ConfigurationWithFactoryBeanEarlyDeductionTests {
@Test
void preFreezeDirect() {
@ -82,6 +85,16 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { @@ -82,6 +85,16 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
assertPostFreeze(AttributeClassConfiguration.class);
}
@Test
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
@ -105,14 +118,13 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { @@ -105,14 +118,13 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
}
}
private void assertPostFreeze(Class<?> configurationClass) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
configurationClass);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configurationClass);
assertContainsMyBeanName(context);
}
private void assertPreFreeze(Class<?> configurationClass,
BeanFactoryPostProcessor... postProcessors) {
private void assertPreFreeze(Class<?> configurationClass, BeanFactoryPostProcessor... postProcessors) {
NameCollectingBeanFactoryPostProcessor postProcessor = new NameCollectingBeanFactoryPostProcessor();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
try (context) {
@ -132,41 +144,38 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { @@ -132,41 +144,38 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
assertThat(names).containsExactly("myBean");
}
private static class NameCollectingBeanFactoryPostProcessor
implements BeanFactoryPostProcessor {
private static class NameCollectingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private String[] names;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
this.names = beanFactory.getBeanNamesForType(MyBean.class, true, false);
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
ResolvableType typeToMatch = ResolvableType.forClassWithGenerics(MyBean.class, String.class);
this.names = beanFactory.getBeanNamesForType(typeToMatch, true, false);
}
public String[] getNames() {
return this.names;
}
}
@Configuration
static class DirectConfiguration {
@Bean
MyBean myBean() {
return new MyBean();
MyBean<String> myBean() {
return new MyBean<>();
}
}
@Configuration
static class GenericMethodConfiguration {
@Bean
FactoryBean<MyBean> myBean() {
return new TestFactoryBean<>(new MyBean());
FactoryBean<MyBean<String>> myBean() {
return new TestFactoryBean<>(new MyBean<>());
}
}
@Configuration
@ -176,13 +185,11 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { @@ -176,13 +185,11 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
MyFactoryBean myBean() {
return new MyFactoryBean();
}
}
@Configuration
@Import(AttributeClassRegistrar.class)
static class AttributeClassConfiguration {
}
static class AttributeClassRegistrar implements ImportBeanDefinitionRegistrar {
@ -191,16 +198,32 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { @@ -191,16 +198,32 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(
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);
}
}
@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 {
}
static class MyBean extends AbstractMyBean {
static class MyBean<T> extends AbstractMyBean {
}
static class TestFactoryBean<T> implements FactoryBean<T> {
@ -220,31 +243,26 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { @@ -220,31 +243,26 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
public Class<?> getObjectType() {
return this.instance.getClass();
}
}
static class MyFactoryBean extends TestFactoryBean<MyBean> {
static class MyFactoryBean extends TestFactoryBean<MyBean<String>> {
public MyFactoryBean() {
super(new MyBean());
super(new MyBean<>());
}
}
static class RawWithAbstractObjectTypeFactoryBean implements FactoryBean<Object> {
private final Object object = new MyBean();
@Override
public Object getObject() {
return object;
public Object getObject() throws Exception {
throw new IllegalStateException();
}
@Override
public Class<?> getObjectType() {
return MyBean.class;
}
}
}

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

@ -39,9 +39,9 @@ import static org.mockito.Mockito.mock; @@ -39,9 +39,9 @@ import static org.mockito.Mockito.mock;
*/
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
@ -198,6 +198,7 @@ class ResultSetWrappingRowSetTests { @@ -198,6 +198,7 @@ class ResultSetWrappingRowSetTests {
doTest(rset, rowset, "test", true);
}
private void doTest(Method rsetMethod, Method rowsetMethod, Object arg, Object ret) throws Exception {
if (arg instanceof String) {
given(resultSet.findColumn((String) arg)).willReturn(1);
@ -207,9 +208,9 @@ class ResultSetWrappingRowSetTests { @@ -207,9 +208,9 @@ class ResultSetWrappingRowSetTests {
given(rsetMethod.invoke(resultSet, arg)).willReturn(ret).willThrow(new SQLException("test"));
}
rowsetMethod.invoke(rowSet, arg);
assertThatExceptionOfType(InvocationTargetException.class).isThrownBy(() ->
rowsetMethod.invoke(rowSet, arg)).
satisfies(ex -> assertThat(ex.getTargetException()).isExactlyInstanceOf(InvalidResultSetAccessException.class));
assertThatExceptionOfType(InvocationTargetException.class)
.isThrownBy(() -> rowsetMethod.invoke(rowSet, arg))
.satisfies(ex -> assertThat(ex.getTargetException()).isExactlyInstanceOf(InvalidResultSetAccessException.class));
}
}

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

@ -51,7 +51,7 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im @@ -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.
* @see #setPropagationBehavior
* @see #setIsolationLevel
@ -75,7 +75,7 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im @@ -75,7 +75,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.
* @param propagationBehavior one of the propagation constants in the
* TransactionDefinition interface

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

@ -1,5 +1,5 @@ @@ -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.
@ -234,11 +234,13 @@ public abstract class AbstractReactiveTransactionManager @@ -234,11 +234,13 @@ public abstract class AbstractReactiveTransactionManager
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) {
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));
}
/**

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

@ -491,7 +491,8 @@ public abstract class AbstractPlatformTransactionManager @@ -491,7 +491,8 @@ public abstract class AbstractPlatformTransactionManager
}
}
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
// PROPAGATION_REQUIRED, PROPAGATION_SUPPORTS, PROPAGATION_MANDATORY:
// regular participation in existing transaction.
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}

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

@ -1,5 +1,5 @@ @@ -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.
@ -90,7 +90,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri @@ -90,7 +90,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.
* @see #setPropagationBehavior
* @see #setIsolationLevel
@ -118,7 +118,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri @@ -118,7 +118,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.
* @param propagationBehavior one of the propagation constants in the
* TransactionDefinition interface

Loading…
Cancel
Save