HHH-12384 Introduce new hibernate.bytecode.enforce_legacy_proxy_classnames configuration property
This commit is contained in:
parent
1f7457133c
commit
432d3a29fa
|
@ -401,6 +401,9 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
|
|||
`*hibernate.bytecode.use_reflection_optimizer*` (e.g. `true` or `false` (default value))::
|
||||
Should we use reflection optimization? The reflection optimizer implements the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/bytecode/spi/ReflectionOptimizer.html[`ReflectionOptimizer`] interface and improves entity instantiation and property getter/setter calls.
|
||||
|
||||
`*hibernate.bytecode.enforce_legacy_proxy_classnames*` (e.g. `true` or `false` (default value))::
|
||||
Some other libraries, such as Spring, used to depend on a specific naming pattern used for proxy classes generated at runtime. Set this to `true` to have proxy class names conform to the old pattern.
|
||||
|
||||
[[configurations-query]]
|
||||
=== Query settings
|
||||
|
||||
|
|
|
@ -13,18 +13,22 @@ import java.util.Set;
|
|||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.bytecode.spi.BasicProxyFactory;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.proxy.ProxyConfiguration;
|
||||
|
||||
import net.bytebuddy.NamingStrategy;
|
||||
import net.bytebuddy.description.modifier.Visibility;
|
||||
import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
|
||||
public class BasicProxyFactoryImpl implements BasicProxyFactory {
|
||||
|
||||
private static final Class[] NO_INTERFACES = new Class[0];
|
||||
private static final NamingStrategy PROXY_NAMING = Environment.useLegacyProxyClassnames() ?
|
||||
new NamingStrategy.SuffixingRandom( "HibernateBasicProxy$" ) :
|
||||
new NamingStrategy.SuffixingRandom( "HibernateBasicProxy" );
|
||||
|
||||
private final Class proxyClass;
|
||||
|
||||
|
@ -42,7 +46,7 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory {
|
|||
}
|
||||
|
||||
this.proxyClass = bytebuddy.getCurrentyByteBuddy()
|
||||
.with( new AuxiliaryType.NamingStrategy.SuffixingRandom( "HibernateBasicProxy" ) )
|
||||
.with( PROXY_NAMING )
|
||||
.subclass( superClass == null ? Object.class : superClass )
|
||||
.implement( interfaces == null ? NO_INTERFACES : interfaces )
|
||||
.defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE )
|
||||
|
|
|
@ -851,6 +851,15 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
|
|||
*/
|
||||
String USE_REFLECTION_OPTIMIZER = "hibernate.bytecode.use_reflection_optimizer";
|
||||
|
||||
/**
|
||||
* Configure the global BytecodeProvider implementation to generate class names matching the
|
||||
* existing naming patterns.
|
||||
* It is not a good idea to rely on a classname to check if a class is an Hibernate proxy,
|
||||
* yet some frameworks are currently relying on this.
|
||||
* This option is disabled by default and will log a deprecation warning when enabled.
|
||||
*/
|
||||
String ENFORCE_LEGACY_PROXY_CLASSNAMES = "hibernate.bytecode.enforce_legacy_proxy_classnames";
|
||||
|
||||
/**
|
||||
* The classname of the HQL query parser factory
|
||||
*/
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.Version;
|
|||
import org.hibernate.bytecode.spi.BytecodeProvider;
|
||||
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.log.UnsupportedLogger;
|
||||
import org.hibernate.internal.util.ConfigHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
||||
|
@ -155,6 +156,7 @@ public final class Environment implements AvailableSettings {
|
|||
private static final BytecodeProvider BYTECODE_PROVIDER_INSTANCE;
|
||||
private static final boolean ENABLE_BINARY_STREAMS;
|
||||
private static final boolean ENABLE_REFLECTION_OPTIMIZER;
|
||||
private static final boolean ENABLE_LEGACY_PROXY_CLASSNAMES;
|
||||
|
||||
private static final Properties GLOBAL_PROPERTIES;
|
||||
|
||||
|
@ -235,6 +237,12 @@ public final class Environment implements AvailableSettings {
|
|||
LOG.usingReflectionOptimizer();
|
||||
}
|
||||
|
||||
ENABLE_LEGACY_PROXY_CLASSNAMES = ConfigurationHelper.getBoolean( ENFORCE_LEGACY_PROXY_CLASSNAMES, GLOBAL_PROPERTIES );
|
||||
if ( ENABLE_LEGACY_PROXY_CLASSNAMES ) {
|
||||
final UnsupportedLogger unsupportedLogger = Logger.getMessageLogger( UnsupportedLogger.class, Environment.class.getName() );
|
||||
unsupportedLogger.usingLegacyClassnamesForProxies();
|
||||
}
|
||||
|
||||
BYTECODE_PROVIDER_INSTANCE = buildBytecodeProvider( GLOBAL_PROPERTIES );
|
||||
}
|
||||
|
||||
|
@ -299,6 +307,15 @@ public final class Environment implements AvailableSettings {
|
|||
return BYTECODE_PROVIDER_INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if global option org.hibernate.cfg.AvailableSettings#ENFORCE_LEGACY_PROXY_CLASSNAMES was enabled
|
||||
* @deprecated This option will be removed soon and should not be relied on.
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean useLegacyProxyClassnames() {
|
||||
return ENABLE_LEGACY_PROXY_CLASSNAMES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disallow instantiation
|
||||
*/
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.jboss.logging.annotations.Cause;
|
|||
import org.jboss.logging.annotations.LogMessage;
|
||||
import org.jboss.logging.annotations.Message;
|
||||
import org.jboss.logging.annotations.MessageLogger;
|
||||
import org.jboss.logging.annotations.ValidIdRange;
|
||||
|
||||
import static org.jboss.logging.Logger.Level.DEBUG;
|
||||
import static org.jboss.logging.Logger.Level.ERROR;
|
||||
|
@ -56,6 +57,7 @@ import static org.jboss.logging.Logger.Level.WARN;
|
|||
* New messages must be added after the last message defined to ensure message codes are unique.
|
||||
*/
|
||||
@MessageLogger(projectCode = "HHH")
|
||||
@ValidIdRange( min = 1, max = 10000 )
|
||||
public interface CoreMessageLogger extends BasicLogger {
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
|
@ -1804,4 +1806,5 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
@Message(value = "The query: [%s] attempts to update an immutable entity: %s",
|
||||
id = 487)
|
||||
void immutableEntityUpdateQuery(String sourceQuery, String querySpaces);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.internal.log;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.jboss.logging.annotations.LogMessage;
|
||||
import org.jboss.logging.annotations.Message;
|
||||
import org.jboss.logging.annotations.MessageLogger;
|
||||
import org.jboss.logging.annotations.ValidIdRange;
|
||||
|
||||
import static org.jboss.logging.Logger.Level.WARN;
|
||||
|
||||
/**
|
||||
* Class to consolidate logging about usage of features which should
|
||||
* never be used.
|
||||
* Such features might have been introduced for practical reasons so
|
||||
* that people who really know what they want can use them, with the
|
||||
* understanding that they should find a better alternative.
|
||||
*
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
@MessageLogger( projectCode = "HHH" )
|
||||
@ValidIdRange( min = 90002001, max = 90003000 )
|
||||
public interface UnsupportedLogger {
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "Global configuration option '" + AvailableSettings.ENFORCE_LEGACY_PROXY_CLASSNAMES + "' was enabled. " +
|
||||
"Generated proxies will use backwards compatible classnames. This option is unsupported and will be removed.",
|
||||
id = 90002001)
|
||||
void usingLegacyClassnamesForProxies();
|
||||
|
||||
}
|
|
@ -16,6 +16,7 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
|
@ -34,11 +35,21 @@ import net.bytebuddy.implementation.MethodDelegation;
|
|||
import net.bytebuddy.implementation.SuperMethodCall;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isFinalizer;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isSynthetic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isVirtual;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.returns;
|
||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.*;
|
||||
|
||||
public class ByteBuddyProxyFactory implements ProxyFactory, Serializable {
|
||||
|
||||
private static final CoreMessageLogger LOG = messageLogger( ByteBuddyProxyFactory.class );
|
||||
private static final NamingStrategy PROXY_NAMING = Environment.useLegacyProxyClassnames() ?
|
||||
new NamingStrategy.SuffixingRandom( "HibernateProxy$" ) :
|
||||
new NamingStrategy.SuffixingRandom( "HibernateProxy" );
|
||||
|
||||
private Class persistentClass;
|
||||
private String entityName;
|
||||
|
@ -91,7 +102,7 @@ public class ByteBuddyProxyFactory implements ProxyFactory, Serializable {
|
|||
return cacheForProxies.findOrInsert( persistentClass.getClassLoader(), new TypeCache.SimpleKey(key), () ->
|
||||
ByteBuddyState.getStaticByteBuddyInstance()
|
||||
.ignore( isSynthetic().and( named( "getMetaClass" ).and( returns( td -> "groovy.lang.MetaClass".equals( td.getName() ) ) ) ) )
|
||||
.with( new NamingStrategy.SuffixingRandom( "HibernateProxy" ) )
|
||||
.with( PROXY_NAMING )
|
||||
.subclass( interfaces.length == 1 ? persistentClass : Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING )
|
||||
.implement( (Type[]) interfaces )
|
||||
.method( isVirtual().and( not( isFinalizer() ) ) )
|
||||
|
|
Loading…
Reference in New Issue