Skip to content

Commit e901516

Browse files
committed
Make SpringPersistenceUnitInfo public for custom bootstrapping purposes
See gh-35622
1 parent 2f8d52f commit e901516

3 files changed

Lines changed: 60 additions & 18 deletions

File tree

spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ public PersistenceUnitInfo obtainDefaultPersistenceUnitInfo() {
675675
}
676676
SpringPersistenceUnitInfo pui = this.persistenceUnitInfos.values().iterator().next();
677677
this.persistenceUnitInfos.clear();
678-
return pui.toSmartPersistenceUnitInfo();
678+
return pui.asStandardPersistenceUnitInfo();
679679
}
680680

681681
@Override
@@ -691,7 +691,7 @@ public PersistenceUnitInfo obtainPersistenceUnitInfo(String persistenceUnitName)
691691
"Persistence unit with name '" + persistenceUnitName + "' already obtained");
692692
}
693693
}
694-
return pui.toSmartPersistenceUnitInfo();
694+
return pui.asStandardPersistenceUnitInfo();
695695
}
696696

697697
}

spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
* Spring's mutable equivalent of the JPA
3535
* {@link jakarta.persistence.spi.PersistenceUnitInfo} interface,
3636
* used to bootstrap an {@code EntityManagerFactory} in a container.
37+
* This is the type exposed to {@link PersistenceUnitPostProcessor}.
3738
*
3839
* <p>This implementation is largely a JavaBean, offering mutators
3940
* for all standard {@code PersistenceUnitInfo} properties.
@@ -42,10 +43,16 @@
4243
* (for achieving compatibility between JPA 3.2 and 4.0 and for preventing
4344
* late mutation attempts through {@code PersistenceUnitInfo} downcasts).
4445
*
46+
* <p>For custom bootstrapping purposes, use {@link SpringPersistenceUnitInfo}
47+
* instead, turning it into a {@code jakarta.persistence.spi.PersistenceUnitInfo}
48+
* through {@link SpringPersistenceUnitInfo#asStandardPersistenceUnitInfo()}.
49+
*
4550
* @author Rod Johnson
4651
* @author Juergen Hoeller
4752
* @author Costin Leau
4853
* @since 2.0
54+
* @see PersistenceUnitPostProcessor#postProcessPersistenceUnitInfo
55+
* @see SpringPersistenceUnitInfo#asStandardPersistenceUnitInfo()
4956
*/
5057
public class MutablePersistenceUnitInfo {
5158

spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SpringPersistenceUnitInfo.java

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import jakarta.persistence.PersistenceUnitTransactionType;
2424
import jakarta.persistence.spi.ClassTransformer;
25+
import jakarta.persistence.spi.PersistenceUnitInfo;
2526
import org.apache.commons.logging.LogFactory;
2627
import org.jspecify.annotations.Nullable;
2728

@@ -35,26 +36,56 @@
3536
* Subclass of {@link MutablePersistenceUnitInfo} that adds instrumentation hooks based on
3637
* Spring's {@link org.springframework.instrument.classloading.LoadTimeWeaver} abstraction.
3738
*
38-
* <p>This class is restricted to package visibility, in contrast to its superclass.
39+
* <p>As of 7.0, this class is public for custom bootstrapping purposes. A fully configured
40+
* {@code SpringPersistenceUnitInfo} instance can be turned into a standard JPA descriptor
41+
* through {@link #asStandardPersistenceUnitInfo} (returning a JPA 3.2/4.0 adapted proxy).
42+
*
43+
* <p>Note: For post-processing within a {@code LocalContainerEntityManagerFactoryBean}
44+
* bootstrap, the base type {@code MutablePersistenceUnitInfo} is entirely sufficient.
3945
*
4046
* @author Rod Johnson
4147
* @author Juergen Hoeller
4248
* @author Costin Leau
43-
* @since 2.0
44-
* @see PersistenceUnitManager
49+
* @since 7.0
50+
* @see DefaultPersistenceUnitManager
4551
*/
46-
class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
52+
public class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
4753

4854
private @Nullable LoadTimeWeaver loadTimeWeaver;
4955

5056
private @Nullable ClassLoader classLoader;
5157

5258

59+
/**
60+
* Construct a new SpringPersistenceUnitInfo for custom purposes.
61+
* @param loadTimeWeaver the LoadTimeWeaver to use
62+
*/
63+
public SpringPersistenceUnitInfo(LoadTimeWeaver loadTimeWeaver) {
64+
init(loadTimeWeaver);
65+
}
66+
67+
/**
68+
* Construct a new SpringPersistenceUnitInfo for custom purposes.
69+
* @param classLoader the ClassLoader to use
70+
*/
71+
public SpringPersistenceUnitInfo(ClassLoader classLoader) {
72+
init(classLoader);
73+
}
74+
75+
/**
76+
* Construct a SpringPersistenceUnitInfo for internal purposes.
77+
* @see #init(LoadTimeWeaver)
78+
* @see #init(ClassLoader)
79+
*/
80+
SpringPersistenceUnitInfo() {
81+
}
82+
83+
5384
/**
5485
* Initialize this PersistenceUnitInfo with the LoadTimeWeaver SPI interface
5586
* used by Spring to add instrumentation to the current class loader.
5687
*/
57-
public void init(LoadTimeWeaver loadTimeWeaver) {
88+
void init(LoadTimeWeaver loadTimeWeaver) {
5889
Assert.notNull(loadTimeWeaver, "LoadTimeWeaver must not be null");
5990
this.loadTimeWeaver = loadTimeWeaver;
6091
this.classLoader = loadTimeWeaver.getInstrumentableClassLoader();
@@ -64,11 +95,10 @@ public void init(LoadTimeWeaver loadTimeWeaver) {
6495
* Initialize this PersistenceUnitInfo with the current class loader
6596
* (instead of with a LoadTimeWeaver).
6697
*/
67-
public void init(@Nullable ClassLoader classLoader) {
98+
void init(@Nullable ClassLoader classLoader) {
6899
this.classLoader = classLoader;
69100
}
70101

71-
72102
/**
73103
* This implementation returns the LoadTimeWeaver's instrumentable ClassLoader,
74104
* if specified.
@@ -102,20 +132,26 @@ public ClassLoader getNewTempClassLoader() {
102132
return tcl;
103133
}
104134

105-
106135
/**
107-
* Expose a {@link SmartPersistenceUnitInfo} proxy for the persistence unit
108-
* configuration in this {@link MutablePersistenceUnitInfo} instance.
109-
* @since 7.0
136+
* Expose a standard {@code jakarta.persistence.spi.PersistenceUnitInfo} proxy for the
137+
* persistence unit configuration in this {@code SpringPersistenceUnitInfo} instance.
138+
* <p>The returned proxy implements {@code jakarta.persistence.spi.PersistenceUnitInfo}
139+
* (and its extended variant {@link SmartPersistenceUnitInfo}) for use with persistence
140+
* provider bootstrapping. Note that the returned proxy is effectively unmodifiable and
141+
* cannot be downcast to {@code Mutable/SpringPersistenceUnitInfo}.
110142
*/
111-
public SmartPersistenceUnitInfo toSmartPersistenceUnitInfo() {
112-
return (SmartPersistenceUnitInfo) Proxy.newProxyInstance(getClass().getClassLoader(),
143+
public PersistenceUnitInfo asStandardPersistenceUnitInfo() {
144+
return (PersistenceUnitInfo) Proxy.newProxyInstance(getClass().getClassLoader(),
113145
new Class<?>[] {SmartPersistenceUnitInfo.class},
114-
new JpaPersistenceUnitInfoInvocationHandler());
146+
new SmartPersistenceUnitInfoInvocationHandler());
115147
}
116148

117149

118-
private class JpaPersistenceUnitInfoInvocationHandler implements InvocationHandler {
150+
/**
151+
* Invocation handler for a JPA-compliant {@link SmartPersistenceUnitInfo} proxy,
152+
* delegating to the corresponding methods on {@link SpringPersistenceUnitInfo}.
153+
*/
154+
private class SmartPersistenceUnitInfoInvocationHandler implements InvocationHandler {
119155

120156
@SuppressWarnings("unchecked")
121157
@Override
@@ -127,7 +163,6 @@ private class JpaPersistenceUnitInfoInvocationHandler implements InvocationHandl
127163

128164
// Regular methods to be delegated to SpringPersistenceUnitInfo
129165
Method targetMethod = SpringPersistenceUnitInfo.class.getMethod(method.getName(), method.getParameterTypes());
130-
ReflectionUtils.makeAccessible(targetMethod);
131166
Object returnValue = ReflectionUtils.invokeMethod(targetMethod, SpringPersistenceUnitInfo.this, args);
132167

133168
// Special handling for JPA 3.2 vs 4.0 getTransactionType() return type

0 commit comments

Comments
 (0)