Browse Source

Make SpringPersistenceUnitInfo public for custom bootstrapping purposes

See gh-35622
pull/35641/head
Juergen Hoeller 2 months ago
parent
commit
e901516732
  1. 4
      spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java
  2. 7
      spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java
  3. 67
      spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SpringPersistenceUnitInfo.java

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

@ -675,7 +675,7 @@ public class DefaultPersistenceUnitManager
} }
SpringPersistenceUnitInfo pui = this.persistenceUnitInfos.values().iterator().next(); SpringPersistenceUnitInfo pui = this.persistenceUnitInfos.values().iterator().next();
this.persistenceUnitInfos.clear(); this.persistenceUnitInfos.clear();
return pui.toSmartPersistenceUnitInfo(); return pui.asStandardPersistenceUnitInfo();
} }
@Override @Override
@ -691,7 +691,7 @@ public class DefaultPersistenceUnitManager
"Persistence unit with name '" + persistenceUnitName + "' already obtained"); "Persistence unit with name '" + persistenceUnitName + "' already obtained");
} }
} }
return pui.toSmartPersistenceUnitInfo(); return pui.asStandardPersistenceUnitInfo();
} }
} }

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

@ -34,6 +34,7 @@ import org.springframework.util.Assert;
* Spring's mutable equivalent of the JPA * Spring's mutable equivalent of the JPA
* {@link jakarta.persistence.spi.PersistenceUnitInfo} interface, * {@link jakarta.persistence.spi.PersistenceUnitInfo} interface,
* used to bootstrap an {@code EntityManagerFactory} in a container. * used to bootstrap an {@code EntityManagerFactory} in a container.
* This is the type exposed to {@link PersistenceUnitPostProcessor}.
* *
* <p>This implementation is largely a JavaBean, offering mutators * <p>This implementation is largely a JavaBean, offering mutators
* for all standard {@code PersistenceUnitInfo} properties. * for all standard {@code PersistenceUnitInfo} properties.
@ -42,10 +43,16 @@ import org.springframework.util.Assert;
* (for achieving compatibility between JPA 3.2 and 4.0 and for preventing * (for achieving compatibility between JPA 3.2 and 4.0 and for preventing
* late mutation attempts through {@code PersistenceUnitInfo} downcasts). * late mutation attempts through {@code PersistenceUnitInfo} downcasts).
* *
* <p>For custom bootstrapping purposes, use {@link SpringPersistenceUnitInfo}
* instead, turning it into a {@code jakarta.persistence.spi.PersistenceUnitInfo}
* through {@link SpringPersistenceUnitInfo#asStandardPersistenceUnitInfo()}.
*
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Costin Leau * @author Costin Leau
* @since 2.0 * @since 2.0
* @see PersistenceUnitPostProcessor#postProcessPersistenceUnitInfo
* @see SpringPersistenceUnitInfo#asStandardPersistenceUnitInfo()
*/ */
public class MutablePersistenceUnitInfo { public class MutablePersistenceUnitInfo {

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

@ -22,6 +22,7 @@ import java.lang.reflect.Proxy;
import jakarta.persistence.PersistenceUnitTransactionType; import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.spi.ClassTransformer; import jakarta.persistence.spi.ClassTransformer;
import jakarta.persistence.spi.PersistenceUnitInfo;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
@ -35,26 +36,56 @@ import org.springframework.util.ReflectionUtils;
* Subclass of {@link MutablePersistenceUnitInfo} that adds instrumentation hooks based on * Subclass of {@link MutablePersistenceUnitInfo} that adds instrumentation hooks based on
* Spring's {@link org.springframework.instrument.classloading.LoadTimeWeaver} abstraction. * Spring's {@link org.springframework.instrument.classloading.LoadTimeWeaver} abstraction.
* *
* <p>This class is restricted to package visibility, in contrast to its superclass. * <p>As of 7.0, this class is public for custom bootstrapping purposes. A fully configured
* {@code SpringPersistenceUnitInfo} instance can be turned into a standard JPA descriptor
* through {@link #asStandardPersistenceUnitInfo} (returning a JPA 3.2/4.0 adapted proxy).
*
* <p>Note: For post-processing within a {@code LocalContainerEntityManagerFactoryBean}
* bootstrap, the base type {@code MutablePersistenceUnitInfo} is entirely sufficient.
* *
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Costin Leau * @author Costin Leau
* @since 2.0 * @since 7.0
* @see PersistenceUnitManager * @see DefaultPersistenceUnitManager
*/ */
class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo { public class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
private @Nullable LoadTimeWeaver loadTimeWeaver; private @Nullable LoadTimeWeaver loadTimeWeaver;
private @Nullable ClassLoader classLoader; private @Nullable ClassLoader classLoader;
/**
* Construct a new SpringPersistenceUnitInfo for custom purposes.
* @param loadTimeWeaver the LoadTimeWeaver to use
*/
public SpringPersistenceUnitInfo(LoadTimeWeaver loadTimeWeaver) {
init(loadTimeWeaver);
}
/**
* Construct a new SpringPersistenceUnitInfo for custom purposes.
* @param classLoader the ClassLoader to use
*/
public SpringPersistenceUnitInfo(ClassLoader classLoader) {
init(classLoader);
}
/**
* Construct a SpringPersistenceUnitInfo for internal purposes.
* @see #init(LoadTimeWeaver)
* @see #init(ClassLoader)
*/
SpringPersistenceUnitInfo() {
}
/** /**
* Initialize this PersistenceUnitInfo with the LoadTimeWeaver SPI interface * Initialize this PersistenceUnitInfo with the LoadTimeWeaver SPI interface
* used by Spring to add instrumentation to the current class loader. * used by Spring to add instrumentation to the current class loader.
*/ */
public void init(LoadTimeWeaver loadTimeWeaver) { void init(LoadTimeWeaver loadTimeWeaver) {
Assert.notNull(loadTimeWeaver, "LoadTimeWeaver must not be null"); Assert.notNull(loadTimeWeaver, "LoadTimeWeaver must not be null");
this.loadTimeWeaver = loadTimeWeaver; this.loadTimeWeaver = loadTimeWeaver;
this.classLoader = loadTimeWeaver.getInstrumentableClassLoader(); this.classLoader = loadTimeWeaver.getInstrumentableClassLoader();
@ -64,11 +95,10 @@ class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
* Initialize this PersistenceUnitInfo with the current class loader * Initialize this PersistenceUnitInfo with the current class loader
* (instead of with a LoadTimeWeaver). * (instead of with a LoadTimeWeaver).
*/ */
public void init(@Nullable ClassLoader classLoader) { void init(@Nullable ClassLoader classLoader) {
this.classLoader = classLoader; this.classLoader = classLoader;
} }
/** /**
* This implementation returns the LoadTimeWeaver's instrumentable ClassLoader, * This implementation returns the LoadTimeWeaver's instrumentable ClassLoader,
* if specified. * if specified.
@ -102,20 +132,26 @@ class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
return tcl; return tcl;
} }
/** /**
* Expose a {@link SmartPersistenceUnitInfo} proxy for the persistence unit * Expose a standard {@code jakarta.persistence.spi.PersistenceUnitInfo} proxy for the
* configuration in this {@link MutablePersistenceUnitInfo} instance. * persistence unit configuration in this {@code SpringPersistenceUnitInfo} instance.
* @since 7.0 * <p>The returned proxy implements {@code jakarta.persistence.spi.PersistenceUnitInfo}
* (and its extended variant {@link SmartPersistenceUnitInfo}) for use with persistence
* provider bootstrapping. Note that the returned proxy is effectively unmodifiable and
* cannot be downcast to {@code Mutable/SpringPersistenceUnitInfo}.
*/ */
public SmartPersistenceUnitInfo toSmartPersistenceUnitInfo() { public PersistenceUnitInfo asStandardPersistenceUnitInfo() {
return (SmartPersistenceUnitInfo) Proxy.newProxyInstance(getClass().getClassLoader(), return (PersistenceUnitInfo) Proxy.newProxyInstance(getClass().getClassLoader(),
new Class<?>[] {SmartPersistenceUnitInfo.class}, new Class<?>[] {SmartPersistenceUnitInfo.class},
new JpaPersistenceUnitInfoInvocationHandler()); new SmartPersistenceUnitInfoInvocationHandler());
} }
private class JpaPersistenceUnitInfoInvocationHandler implements InvocationHandler { /**
* Invocation handler for a JPA-compliant {@link SmartPersistenceUnitInfo} proxy,
* delegating to the corresponding methods on {@link SpringPersistenceUnitInfo}.
*/
private class SmartPersistenceUnitInfoInvocationHandler implements InvocationHandler {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
@ -127,7 +163,6 @@ class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
// Regular methods to be delegated to SpringPersistenceUnitInfo // Regular methods to be delegated to SpringPersistenceUnitInfo
Method targetMethod = SpringPersistenceUnitInfo.class.getMethod(method.getName(), method.getParameterTypes()); Method targetMethod = SpringPersistenceUnitInfo.class.getMethod(method.getName(), method.getParameterTypes());
ReflectionUtils.makeAccessible(targetMethod);
Object returnValue = ReflectionUtils.invokeMethod(targetMethod, SpringPersistenceUnitInfo.this, args); Object returnValue = ReflectionUtils.invokeMethod(targetMethod, SpringPersistenceUnitInfo.this, args);
// Special handling for JPA 3.2 vs 4.0 getTransactionType() return type // Special handling for JPA 3.2 vs 4.0 getTransactionType() return type

Loading…
Cancel
Save