2222
2323import jakarta .persistence .PersistenceUnitTransactionType ;
2424import jakarta .persistence .spi .ClassTransformer ;
25+ import jakarta .persistence .spi .PersistenceUnitInfo ;
2526import org .apache .commons .logging .LogFactory ;
2627import org .jspecify .annotations .Nullable ;
2728
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