diff --git a/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java b/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java index 5b0af83467..7d94fe28bd 100644 --- a/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java +++ b/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -97,7 +97,7 @@ public final class CachedIntrospectionResults { SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME); /** Stores the BeanInfoFactory instances. */ - private static List beanInfoFactories = SpringFactoriesLoader.loadFactories( + private static final List beanInfoFactories = SpringFactoriesLoader.loadFactories( BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader()); private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateResolver.java index bb1740e397..0a1f0a7d69 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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,6 +16,7 @@ package org.springframework.beans.factory.support; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.lang.Nullable; @@ -99,4 +100,22 @@ public interface AutowireCandidateResolver { return null; } + /** + * Return a clone of this resolver instance if necessary, retaining its local + * configuration and allowing for the cloned instance to get associated with + * a new bean factory, or this original instance if there is no such state. + *

The default implementation creates a separate instance via the default + * class constructor, assuming no specific configuration state to copy. + * Subclasses may override this with custom configuration state handling + * or with standard {@link Cloneable} support (as implemented by Spring's + * own configurable {@code AutowireCandidateResolver} variants), or simply + * return {@code this} (as in {@link SimpleAutowireCandidateResolver}). + * @since 5.2.7 + * @see GenericTypeAwareAutowireCandidateResolver#cloneIfNecessary() + * @see DefaultListableBeanFactory#copyConfigurationFrom + */ + default AutowireCandidateResolver cloneIfNecessary() { + return BeanUtils.instantiateClass(getClass()); + } + } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java index e5acd029ea..d5d9b9f871 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -202,7 +202,6 @@ class ConstructorResolver { LinkedList causes = null; for (Constructor candidate : candidates) { - int parameterCount = candidate.getParameterCount(); if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) { @@ -515,8 +514,8 @@ class ConstructorResolver { LinkedList causes = null; for (Method candidate : candidates) { - int parameterCount = candidate.getParameterCount(); + if (parameterCount >= minNrOfArgs) { ArgumentsHolder argsHolder; @@ -679,7 +678,7 @@ class ConstructorResolver { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid constructor argument index: " + index); } - if (index > minNrOfArgs) { + if (index + 1 > minNrOfArgs) { minNrOfArgs = index + 1; } ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue(); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index f242051cb2..7f1bc1dda2 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -46,7 +46,6 @@ import java.util.stream.Stream; import javax.inject.Provider; -import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; import org.springframework.beans.TypeConverter; import org.springframework.beans.factory.BeanCreationException; @@ -156,7 +155,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto private Comparator dependencyComparator; /** Resolver to use for checking if a bean definition is an autowire candidate. */ - private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver(); + private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE; /** Map from dependency type to corresponding autowired value. */ private final Map, Object> resolvableDependencies = new ConcurrentHashMap<>(16); @@ -327,8 +326,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading; this.dependencyComparator = otherListableFactory.dependencyComparator; // A clone of the AutowireCandidateResolver since it is potentially BeanFactoryAware... - setAutowireCandidateResolver( - BeanUtils.instantiateClass(otherListableFactory.getAutowireCandidateResolver().getClass())); + setAutowireCandidateResolver(otherListableFactory.getAutowireCandidateResolver().cloneIfNecessary()); // Make resolvable dependencies (e.g. ResourceLoader) available here as well... this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java index 7143fc9b1f..01b8145090 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -43,7 +43,7 @@ import org.springframework.util.ClassUtils; * @since 4.0 */ public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCandidateResolver - implements BeanFactoryAware { + implements BeanFactoryAware, Cloneable { @Nullable private BeanFactory beanFactory; @@ -177,4 +177,21 @@ public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCan return null; } + + /** + * This implementation clones all instance fields through standard + * {@link Cloneable} support, allowing for subsequent reconfiguration + * of the cloned instance through a fresh {@link #setBeanFactory} call. + * @see #clone() + */ + @Override + public AutowireCandidateResolver cloneIfNecessary() { + try { + return (AutowireCandidateResolver) clone(); + } + catch (CloneNotSupportedException ex) { + throw new IllegalStateException(ex); + } + } + } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java index 17909b5946..f33eeecf16 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -30,6 +30,13 @@ import org.springframework.lang.Nullable; */ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolver { + /** + * Shared instance of {@code SimpleAutowireCandidateResolver}. + * @since 5.2.7 + */ + public static final SimpleAutowireCandidateResolver INSTANCE = new SimpleAutowireCandidateResolver(); + + @Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { return bdHolder.getBeanDefinition().isAutowireCandidate(); @@ -40,6 +47,11 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve return descriptor.isRequired(); } + @Override + public boolean hasQualifier(DependencyDescriptor descriptor) { + return false; + } + @Override @Nullable public Object getSuggestedValue(DependencyDescriptor descriptor) { @@ -52,4 +64,13 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve return null; } + /** + * This implementation returns {@code this} as-is. + * @see #INSTANCE + */ + @Override + public AutowireCandidateResolver cloneIfNecessary() { + return this; + } + } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java index 2601d9c857..d2f619a4d1 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java @@ -254,9 +254,6 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive()); } - /** - * This implementation sets the isolation level but ignores the timeout. - */ @Override protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java index 8d389e6468..f17b82d5f1 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -58,10 +58,10 @@ import org.springframework.util.ClassUtils; * way to set up a shared Hibernate SessionFactory in a Spring application context; the * SessionFactory can then be passed to data access objects via dependency injection. * - *

Compatible with Hibernate 5.0/5.1 as well as 5.2/5.3, as of Spring 5.1. - * Set up with Hibernate 5.3, {@code LocalSessionFactoryBean} is an immediate alternative + *

Compatible with Hibernate 5.0/5.1 as well as 5.2/5.3/5.4, as of Spring 5.2. + * Set up with Hibernate 5.2+, {@code LocalSessionFactoryBean} is an immediate alternative * to {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} for common - * JPA purposes: In particular with Hibernate 5.3, the Hibernate {@code SessionFactory} + * JPA purposes: In particular with Hibernate 5.3/5.4, the Hibernate {@code SessionFactory} * will natively expose the JPA {@code EntityManagerFactory} interface as well, and * Hibernate {@code BeanContainer} integration will be registered out of the box. * In combination with {@link HibernateTransactionManager}, this naturally allows for diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java index 3c8f934788..e6f50a90d6 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -76,12 +76,12 @@ import org.springframework.util.ClassUtils; * Typically combined with {@link HibernateTransactionManager} for declarative * transactions against the {@code SessionFactory} and its JDBC {@code DataSource}. * - *

Compatible with Hibernate 5.0/5.1 as well as 5.2/5.3, as of Spring 5.1. - * Set up with Hibernate 5.2/5.3, this builder is also a convenient way to set up + *

Compatible with Hibernate 5.0/5.1 as well as 5.2/5.3/5.4, as of Spring 5.2. + * Set up with Hibernate 5.2+, this builder is also a convenient way to set up * a JPA {@code EntityManagerFactory} since the Hibernate {@code SessionFactory} * natively exposes the JPA {@code EntityManagerFactory} interface as well now. * - *

This builder supports Hibernate 5.3 {@code BeanContainer} integration, + *

This builder supports Hibernate 5.3/5.4 {@code BeanContainer} integration, * {@link MetadataSources} from custom {@link BootstrapServiceRegistryBuilder} * setup, as well as other advanced Hibernate configuration options beyond the * standard JPA bootstrap contract. diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java index 38e606c022..92064f2a4c 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -63,7 +63,7 @@ import org.springframework.util.ConcurrentReferenceHashMap; * * Please note that Spring's {@link LocalSessionFactoryBean} is an immediate alternative * to {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} for common - * JPA purposes: In particular with Hibernate 5.3, the Hibernate {@code SessionFactory} + * JPA purposes: In particular with Hibernate 5.3/5.4, the Hibernate {@code SessionFactory} * will natively expose the JPA {@code EntityManagerFactory} interface as well, and * Hibernate {@code BeanContainer} integration will be registered out of the box. * diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java index 4ea48ce5e9..06106935b7 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -76,7 +76,7 @@ import org.springframework.util.ReflectionUtils; /** * {@link org.springframework.orm.jpa.JpaDialect} implementation for - * Hibernate EntityManager. Developed against Hibernate 5.1/5.2/5.3. + * Hibernate EntityManager. Developed against Hibernate 5.1/5.2/5.3/5.4. * * @author Juergen Hoeller * @author Costin Leau diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java index 1b8515aca3..c57cb7865f 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -42,7 +42,7 @@ import org.springframework.lang.Nullable; /** * {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate - * EntityManager. Developed and tested against Hibernate 5.0, 5.1, 5.2 and 5.3; + * EntityManager. Developed and tested against Hibernate 5.0, 5.1, 5.2, 5.3, 5.4; * backwards-compatible with Hibernate 4.3 at runtime on a best-effort basis. * *

Exposes Hibernate's persistence provider and EntityManager extension interface, @@ -92,7 +92,7 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { * JDBC Connection. *

See {@link HibernateJpaDialect#setPrepareConnection(boolean)} for details. * This is just a convenience flag passed through to {@code HibernateJpaDialect}. - *

On Hibernate 5.1/5.2, this flag remains {@code true} by default like against + *

On Hibernate 5.1+, this flag remains {@code true} by default like against * previous Hibernate versions. The vendor adapter manually enforces Hibernate's * new connection handling mode {@code DELAYED_ACQUISITION_AND_HOLD} in that case * unless a user-specified connection handling mode property indicates otherwise; @@ -155,9 +155,9 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { } if (connectionReleaseOnClose) { - // Hibernate 5.1/5.2: manually enforce connection release mode ON_CLOSE (the former default) + // Hibernate 5.1+: manually enforce connection release mode ON_CLOSE (the former default) try { - // Try Hibernate 5.2 + // Try Hibernate 5.2+ AvailableSettings.class.getField("CONNECTION_HANDLING"); jpaProperties.put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_HOLD"); } diff --git a/spring-tx/src/main/java/org/springframework/transaction/jta/WebSphereUowTransactionManager.java b/spring-tx/src/main/java/org/springframework/transaction/jta/WebSphereUowTransactionManager.java index 3406f328c8..256cc96529 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/jta/WebSphereUowTransactionManager.java +++ b/spring-tx/src/main/java/org/springframework/transaction/jta/WebSphereUowTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -295,14 +295,14 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager SuspendedResourcesHolder suspendedResources = (!joinTx ? suspend(null) : null); UOWActionAdapter action = null; try { - if (def.getTimeout() > TransactionDefinition.TIMEOUT_DEFAULT) { + boolean actualTransaction = (uowType == UOWManager.UOW_TYPE_GLOBAL_TRANSACTION); + if (actualTransaction && def.getTimeout() > TransactionDefinition.TIMEOUT_DEFAULT) { uowManager.setUOWTimeout(uowType, def.getTimeout()); } if (debug) { logger.debug("Invoking WebSphere UOW action: type=" + uowType + ", join=" + joinTx); } - action = new UOWActionAdapter<>( - def, callback, (uowType == UOWManager.UOW_TYPE_GLOBAL_TRANSACTION), !joinTx, newSynch, debug); + action = new UOWActionAdapter<>(def, callback, actualTransaction, !joinTx, newSynch, debug); uowManager.runUnderUOW(uowType, joinTx, action); if (debug) { logger.debug("Returned from WebSphere UOW action: type=" + uowType + ", join=" + joinTx);