Skip to content

Commit 3a481a7

Browse files
committed
Merge branch '6.0.x'
2 parents 74972fb + f19433f commit 3a481a7

File tree

9 files changed

+69
-54
lines changed

9 files changed

+69
-54
lines changed

spring-context/src/main/java/org/springframework/context/annotation/LoadTimeWeavingConfigurer.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,8 +21,8 @@
2121
/**
2222
* Interface to be implemented by
2323
* {@link org.springframework.context.annotation.Configuration @Configuration}
24-
* classes annotated with {@link EnableLoadTimeWeaving @EnableLoadTimeWeaving} that wish to
25-
* customize the {@link LoadTimeWeaver} instance to be used.
24+
* classes annotated with {@link EnableLoadTimeWeaving @EnableLoadTimeWeaving}
25+
* that wish to customize the {@link LoadTimeWeaver} instance to be used.
2626
*
2727
* <p>See {@link org.springframework.scheduling.annotation.EnableAsync @EnableAsync}
2828
* for usage examples and information on how a default {@code LoadTimeWeaver}
@@ -36,9 +36,9 @@
3636
public interface LoadTimeWeavingConfigurer {
3737

3838
/**
39-
* Create, configure and return the {@code LoadTimeWeaver} instance to be used. Note
40-
* that it is unnecessary to annotate this method with {@code @Bean}, because the
41-
* object returned will automatically be registered as a bean by
39+
* Create, configure and return the {@code LoadTimeWeaver} instance to be used.
40+
* Note that it is unnecessary to annotate this method with {@code @Bean}
41+
* because the object returned will automatically be registered as a bean by
4242
* {@link LoadTimeWeavingConfiguration#loadTimeWeaver()}
4343
*/
4444
LoadTimeWeaver getLoadTimeWeaver();

spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,8 @@ protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory b
769769

770770
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
771771
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
772-
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
772+
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
773+
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
773774
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
774775
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
775776
}

spring-context/src/main/java/org/springframework/context/support/ContextTypeMatchClassLoader.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
2121
import java.util.Map;
2222
import java.util.concurrent.ConcurrentHashMap;
2323

24+
import org.apache.commons.logging.LogFactory;
25+
2426
import org.springframework.core.DecoratingClassLoader;
2527
import org.springframework.core.OverridingClassLoader;
2628
import org.springframework.core.SmartClassLoader;
@@ -45,15 +47,26 @@ class ContextTypeMatchClassLoader extends DecoratingClassLoader implements Smart
4547
}
4648

4749

48-
private static Method findLoadedClassMethod;
50+
@Nullable
51+
private static final Method findLoadedClassMethod;
4952

5053
static {
54+
// Try to enable findLoadedClass optimization which allows us to selectively
55+
// override classes that have not been loaded yet. If not accessible, we will
56+
// always override requested classes, even when the classes have been loaded
57+
// by the parent ClassLoader already and cannot be transformed anymore anyway.
58+
Method method = null;
5159
try {
52-
findLoadedClassMethod = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
60+
method = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
61+
ReflectionUtils.makeAccessible(method);
5362
}
54-
catch (NoSuchMethodException ex) {
55-
throw new IllegalStateException("Invalid [java.lang.ClassLoader] class: no 'findLoadedClass' method defined!");
63+
catch (Throwable ex) {
64+
// Typically a JDK 9+ InaccessibleObjectException...
65+
// Avoid through JVM startup with --add-opens=java.base/java.lang=ALL-UNNAMED
66+
LogFactory.getLog(ContextTypeMatchClassLoader.class).debug(
67+
"ClassLoader.findLoadedClass not accessible -> will always override requested class", ex);
5668
}
69+
findLoadedClassMethod = method;
5770
}
5871

5972

@@ -96,13 +109,14 @@ protected boolean isEligibleForOverriding(String className) {
96109
if (isExcluded(className) || ContextTypeMatchClassLoader.this.isExcluded(className)) {
97110
return false;
98111
}
99-
ReflectionUtils.makeAccessible(findLoadedClassMethod);
100-
ClassLoader parent = getParent();
101-
while (parent != null) {
102-
if (ReflectionUtils.invokeMethod(findLoadedClassMethod, parent, className) != null) {
103-
return false;
112+
if (findLoadedClassMethod != null) {
113+
ClassLoader parent = getParent();
114+
while (parent != null) {
115+
if (ReflectionUtils.invokeMethod(findLoadedClassMethod, parent, className) != null) {
116+
return false;
117+
}
118+
parent = parent.getParent();
104119
}
105-
parent = parent.getParent();
106120
}
107121
return true;
108122
}

spring-context/src/test/java/org/springframework/context/annotation/EnableLoadTimeWeavingTests.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void enableLTW_withAjWeavingEnabled() {
7979

8080

8181
@Configuration
82-
@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.DISABLED)
82+
@EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.DISABLED)
8383
static class EnableLTWConfig_withAjWeavingDisabled implements LoadTimeWeavingConfigurer {
8484

8585
@Override
@@ -88,8 +88,9 @@ public LoadTimeWeaver getLoadTimeWeaver() {
8888
}
8989
}
9090

91+
9192
@Configuration
92-
@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.AUTODETECT)
93+
@EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.AUTODETECT)
9394
static class EnableLTWConfig_withAjWeavingAutodetect implements LoadTimeWeavingConfigurer {
9495

9596
@Override
@@ -98,8 +99,9 @@ public LoadTimeWeaver getLoadTimeWeaver() {
9899
}
99100
}
100101

102+
101103
@Configuration
102-
@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
104+
@EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.ENABLED)
103105
static class EnableLTWConfig_withAjWeavingEnabled implements LoadTimeWeavingConfigurer {
104106

105107
@Override

spring-context/src/test/java/org/springframework/instrument/classloading/ReflectiveLoadTimeWeaverTests.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -85,35 +85,29 @@ public static class JustAddTransformerClassLoader extends ClassLoader {
8585

8686
private int numTimesAddTransformerCalled = 0;
8787

88-
8988
public int getNumTimesGetThrowawayClassLoaderCalled() {
9089
return this.numTimesAddTransformerCalled;
9190
}
9291

93-
9492
public void addTransformer(ClassFileTransformer transformer) {
9593
++this.numTimesAddTransformerCalled;
9694
}
97-
9895
}
9996

10097

10198
public static final class TotallyCompliantClassLoader extends JustAddTransformerClassLoader {
10299

103100
private int numTimesGetThrowawayClassLoaderCalled = 0;
104101

105-
106102
@Override
107103
public int getNumTimesGetThrowawayClassLoaderCalled() {
108104
return this.numTimesGetThrowawayClassLoaderCalled;
109105
}
110106

111-
112107
public ClassLoader getThrowawayClassLoader() {
113108
++this.numTimesGetThrowawayClassLoaderCalled;
114109
return getClass().getClassLoader();
115110
}
116-
117111
}
118112

119113
}

spring-core/src/main/java/org/springframework/cglib/core/ReflectUtils.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.beans.PropertyDescriptor;
2323
import java.lang.invoke.MethodHandles;
2424
import java.lang.reflect.Constructor;
25+
import java.lang.reflect.InaccessibleObjectException;
2526
import java.lang.reflect.InvocationTargetException;
2627
import java.lang.reflect.Member;
2728
import java.lang.reflect.Method;
@@ -508,14 +509,14 @@ public static Class defineClass(String className, byte[] b, ClassLoader loader,
508509
catch (InvocationTargetException ex) {
509510
throw new CodeGenerationException(ex.getTargetException());
510511
}
511-
catch (Throwable ex) {
512-
// Fall through if setAccessible fails with InaccessibleObjectException on JDK 9+
513-
// (on the module path and/or with a JVM bootstrapped with --illegal-access=deny)
514-
if (!ex.getClass().getName().endsWith("InaccessibleObjectException")) {
515-
throw new CodeGenerationException(ex);
516-
}
512+
catch (InaccessibleObjectException ex) {
513+
// setAccessible failed with JDK 9+ InaccessibleObjectException -> fall through
514+
// Avoid through JVM startup with --add-opens=java.base/java.lang=ALL-UNNAMED
517515
t = ex;
518516
}
517+
catch (Throwable ex) {
518+
throw new CodeGenerationException(ex);
519+
}
519520
}
520521
}
521522

@@ -525,13 +526,14 @@ public static Class defineClass(String className, byte[] b, ClassLoader loader,
525526
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(contextClass, MethodHandles.lookup());
526527
c = lookup.defineClass(b);
527528
}
528-
catch (IllegalAccessException ex) {
529+
catch (LinkageError | IllegalAccessException ex) {
529530
throw new CodeGenerationException(ex) {
530531
@Override
531532
public String getMessage() {
532533
return "ClassLoader mismatch for [" + contextClass.getName() +
533534
"]: JVM should be started with --add-opens=java.base/java.lang=ALL-UNNAMED " +
534-
"for ClassLoader.defineClass to be accessible on " + loader.getClass().getName();
535+
"for ClassLoader.defineClass to be accessible on " + loader.getClass().getName() +
536+
"; consider co-locating the affected class in that target ClassLoader instead.";
535537
}
536538
};
537539
}

spring-core/src/main/java/org/springframework/util/ReflectionUtils.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -507,24 +507,16 @@ private static List<Method> findConcreteMethodsOnInterfaces(Class<?> clazz) {
507507
* @see java.lang.Object#equals(Object)
508508
*/
509509
public static boolean isEqualsMethod(@Nullable Method method) {
510-
if (method == null) {
511-
return false;
512-
}
513-
if (method.getParameterCount() != 1) {
514-
return false;
515-
}
516-
if (!method.getName().equals("equals")) {
517-
return false;
518-
}
519-
return method.getParameterTypes()[0] == Object.class;
510+
return (method != null && method.getParameterCount() == 1 && method.getName().equals("equals") &&
511+
method.getParameterTypes()[0] == Object.class);
520512
}
521513

522514
/**
523515
* Determine whether the given method is a "hashCode" method.
524516
* @see java.lang.Object#hashCode()
525517
*/
526518
public static boolean isHashCodeMethod(@Nullable Method method) {
527-
return method != null && method.getParameterCount() == 0 && method.getName().equals("hashCode");
519+
return (method != null && method.getParameterCount() == 0 && method.getName().equals("hashCode"));
528520
}
529521

530522
/**

spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTransactionManager.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,18 @@
9797
* support nested transactions! Hence, do not expect Hibernate access code to
9898
* semantically participate in a nested transaction.</i>
9999
*
100+
* <p><b>NOTE: Hibernate ORM 6.x is officially only supported as a JPA provider.
101+
* Please use {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean}
102+
* with {@link org.springframework.orm.jpa.JpaTransactionManager} there instead.</b>
103+
*
100104
* @author Juergen Hoeller
101105
* @since 4.2
102106
* @see #setSessionFactory
103-
* @see #setDataSource
104107
* @see SessionFactory#getCurrentSession()
105-
* @see DataSourceUtils#getConnection
106-
* @see DataSourceUtils#releaseConnection
107108
* @see org.springframework.jdbc.core.JdbcTemplate
108109
* @see org.springframework.jdbc.support.JdbcTransactionManager
109-
* @see org.springframework.transaction.jta.JtaTransactionManager
110+
* @see org.springframework.orm.jpa.JpaTransactionManager
111+
* @see org.springframework.orm.jpa.vendor.HibernateJpaDialect
110112
*/
111113
@SuppressWarnings("serial")
112114
public class HibernateTransactionManager extends AbstractPlatformTransactionManager
@@ -271,7 +273,11 @@ public void setPrepareConnection(boolean prepareConnection) {
271273
* @see Connection#setHoldability
272274
* @see ResultSet#HOLD_CURSORS_OVER_COMMIT
273275
* @see #disconnectOnCompletion(Session)
276+
* @deprecated as of 5.3.29 since Hibernate 5.x aggressively closes ResultSets on commit,
277+
* making it impossible to rely on ResultSet holdability. Also, Spring does not provide
278+
* an equivalent setting on {@link org.springframework.orm.jpa.JpaTransactionManager}.
274279
*/
280+
@Deprecated(since = "5.3.29")
275281
public void setAllowResultAccessAfterCompletion(boolean allowResultAccessAfterCompletion) {
276282
this.allowResultAccessAfterCompletion = allowResultAccessAfterCompletion;
277283
}
@@ -487,7 +493,7 @@ protected void doBegin(Object transaction, TransactionDefinition definition) {
487493

488494
session = txObject.getSessionHolder().getSession().unwrap(SessionImplementor.class);
489495

490-
boolean holdabilityNeeded = this.allowResultAccessAfterCompletion && !txObject.isNewSession();
496+
boolean holdabilityNeeded = (this.allowResultAccessAfterCompletion && !txObject.isNewSession());
491497
boolean isolationLevelNeeded = (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT);
492498
if (holdabilityNeeded || isolationLevelNeeded || definition.isReadOnly()) {
493499
if (this.prepareConnection && ConnectionReleaseMode.ON_CLOSE.equals(
@@ -500,7 +506,7 @@ protected void doBegin(Object transaction, TransactionDefinition definition) {
500506
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
501507
txObject.setPreviousIsolationLevel(previousIsolationLevel);
502508
txObject.setReadOnly(definition.isReadOnly());
503-
if (this.allowResultAccessAfterCompletion && !txObject.isNewSession()) {
509+
if (holdabilityNeeded) {
504510
int currentHoldability = con.getHoldability();
505511
if (currentHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
506512
txObject.setPreviousHoldability(currentHoldability);

spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
* {@link HibernateTransactionManager}, this naturally allows for mixing JPA access code
6767
* with native Hibernate access code within the same transaction.
6868
*
69+
* <p><b>NOTE: Hibernate ORM 6.x is officially only supported as a JPA provider.
70+
* Please use {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean}
71+
* with {@link org.springframework.orm.jpa.JpaTransactionManager} there instead.</b>
72+
*
6973
* @author Juergen Hoeller
7074
* @since 4.2
7175
* @see #setDataSource

0 commit comments

Comments
 (0)