HHH-13097 Cache the annotations resolution

This commit is contained in:
Guillaume Smet 2018-11-13 16:08:50 +01:00 committed by Sanne Grinovero
parent d125349c07
commit 4ec71218e9
10 changed files with 203 additions and 166 deletions

View File

@ -17,6 +17,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancementException;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.internal.CoreLogging;
@ -43,7 +44,7 @@ final class BiDirectionalAssociationHandler implements Implementation {
static Implementation wrap(
TypeDescription managedCtClass,
ByteBuddyEnhancementContext enhancementContext,
FieldDescription persistentField,
AnnotatedFieldDescription persistentField,
Implementation implementation) {
if ( !enhancementContext.doBiDirectionalAssociationManagement( persistentField ) ) {
return implementation;
@ -69,17 +70,17 @@ final class BiDirectionalAssociationHandler implements Implementation {
.getType()
.asErasure();
if ( EnhancerImpl.isAnnotationPresent( persistentField, OneToOne.class ) ) {
if ( persistentField.hasAnnotation( OneToOne.class ) ) {
implementation = Advice.withCustomMapping()
.bind( CodeTemplates.FieldValue.class, persistentField )
.bind( CodeTemplates.FieldValue.class, persistentField.getFieldDescription() )
.bind( CodeTemplates.MappedBy.class, mappedBy )
.to( CodeTemplates.OneToOneHandler.class )
.wrap( implementation );
}
if ( EnhancerImpl.isAnnotationPresent( persistentField, OneToMany.class ) ) {
if ( persistentField.hasAnnotation( OneToMany.class ) ) {
implementation = Advice.withCustomMapping()
.bind( CodeTemplates.FieldValue.class, persistentField )
.bind( CodeTemplates.FieldValue.class, persistentField.getFieldDescription() )
.bind( CodeTemplates.MappedBy.class, mappedBy )
.to( persistentField.getType().asErasure().isAssignableTo( Map.class )
? CodeTemplates.OneToManyOnMapHandler.class
@ -87,15 +88,15 @@ final class BiDirectionalAssociationHandler implements Implementation {
.wrap( implementation );
}
if ( EnhancerImpl.isAnnotationPresent( persistentField, ManyToOne.class ) ) {
if ( persistentField.hasAnnotation( ManyToOne.class ) ) {
implementation = Advice.withCustomMapping()
.bind( CodeTemplates.FieldValue.class, persistentField )
.bind( CodeTemplates.FieldValue.class, persistentField.getFieldDescription() )
.bind( CodeTemplates.MappedBy.class, mappedBy )
.to( CodeTemplates.ManyToOneHandler.class )
.wrap( implementation );
}
if ( EnhancerImpl.isAnnotationPresent( persistentField, ManyToMany.class ) ) {
if ( persistentField.hasAnnotation( ManyToMany.class ) ) {
if ( persistentField.getType().asErasure().isAssignableTo( Map.class ) || targetType.isAssignableTo( Map.class ) ) {
log.infof(
@ -107,7 +108,7 @@ final class BiDirectionalAssociationHandler implements Implementation {
}
implementation = Advice.withCustomMapping()
.bind( CodeTemplates.FieldValue.class, persistentField )
.bind( CodeTemplates.FieldValue.class, persistentField.getFieldDescription() )
.bind( CodeTemplates.MappedBy.class, mappedBy )
.to( CodeTemplates.ManyToManyHandler.class )
.wrap( implementation );
@ -116,12 +117,12 @@ final class BiDirectionalAssociationHandler implements Implementation {
return new BiDirectionalAssociationHandler( implementation, targetEntity, targetType, mappedBy );
}
public static TypeDescription getTargetEntityClass(TypeDescription managedCtClass, FieldDescription persistentField) {
public static TypeDescription getTargetEntityClass(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
try {
AnnotationDescription.Loadable<OneToOne> oto = EnhancerImpl.getAnnotation( persistentField, OneToOne.class );
AnnotationDescription.Loadable<OneToMany> otm = EnhancerImpl.getAnnotation( persistentField, OneToMany.class );
AnnotationDescription.Loadable<ManyToOne> mto = EnhancerImpl.getAnnotation( persistentField, ManyToOne.class );
AnnotationDescription.Loadable<ManyToMany> mtm = EnhancerImpl.getAnnotation( persistentField, ManyToMany.class );
AnnotationDescription.Loadable<OneToOne> oto = persistentField.getAnnotation( OneToOne.class );
AnnotationDescription.Loadable<OneToMany> otm = persistentField.getAnnotation( OneToMany.class );
AnnotationDescription.Loadable<ManyToOne> mto = persistentField.getAnnotation( ManyToOne.class );
AnnotationDescription.Loadable<ManyToMany> mtm = persistentField.getAnnotation( ManyToMany.class );
if ( oto == null && otm == null && mto == null && mtm == null ) {
return null;
@ -159,7 +160,7 @@ final class BiDirectionalAssociationHandler implements Implementation {
return entityType( target( persistentField ) );
}
private static TypeDescription.Generic target(FieldDescription persistentField) {
private static TypeDescription.Generic target(AnnotatedFieldDescription persistentField) {
AnnotationDescription.Loadable<Access> access = persistentField.getDeclaringType().asErasure().getDeclaredAnnotations().ofType( Access.class );
if ( access != null && access.loadSilent().value() == AccessType.FIELD ) {
return persistentField.getType();
@ -175,7 +176,7 @@ final class BiDirectionalAssociationHandler implements Implementation {
}
}
private static String getMappedBy(FieldDescription target, TypeDescription targetEntity, ByteBuddyEnhancementContext context) {
private static String getMappedBy(AnnotatedFieldDescription target, TypeDescription targetEntity, ByteBuddyEnhancementContext context) {
String mappedBy = getMappedByNotManyToMany( target );
if ( mappedBy == null || mappedBy.isEmpty() ) {
return getMappedByManyToMany( target, targetEntity, context );
@ -185,19 +186,19 @@ final class BiDirectionalAssociationHandler implements Implementation {
}
}
private static String getMappedByNotManyToMany(FieldDescription target) {
private static String getMappedByNotManyToMany(AnnotatedFieldDescription target) {
try {
AnnotationDescription.Loadable<OneToOne> oto = EnhancerImpl.getAnnotation( target, OneToOne.class );
AnnotationDescription.Loadable<OneToOne> oto = target.getAnnotation( OneToOne.class );
if ( oto != null ) {
return oto.getValue( new MethodDescription.ForLoadedMethod( OneToOne.class.getDeclaredMethod( "mappedBy" ) ) ).resolve( String.class );
}
AnnotationDescription.Loadable<OneToMany> otm = EnhancerImpl.getAnnotation( target, OneToMany.class );
AnnotationDescription.Loadable<OneToMany> otm = target.getAnnotation( OneToMany.class );
if ( otm != null ) {
return otm.getValue( new MethodDescription.ForLoadedMethod( OneToMany.class.getDeclaredMethod( "mappedBy" ) ) ).resolve( String.class );
}
AnnotationDescription.Loadable<ManyToMany> mtm = EnhancerImpl.getAnnotation( target, ManyToMany.class );
AnnotationDescription.Loadable<ManyToMany> mtm = target.getAnnotation( ManyToMany.class );
if ( mtm != null ) {
return mtm.getValue( new MethodDescription.ForLoadedMethod( ManyToMany.class.getDeclaredMethod( "mappedBy" ) ) ).resolve( String.class );
}
@ -208,11 +209,12 @@ final class BiDirectionalAssociationHandler implements Implementation {
return null;
}
private static String getMappedByManyToMany(FieldDescription target, TypeDescription targetEntity, ByteBuddyEnhancementContext context) {
private static String getMappedByManyToMany(AnnotatedFieldDescription target, TypeDescription targetEntity, ByteBuddyEnhancementContext context) {
for ( FieldDescription f : targetEntity.getDeclaredFields() ) {
if ( context.isPersistentField( f )
&& target.getName().equals( getMappedByNotManyToMany( f ) )
&& target.getDeclaringType().asErasure().isAssignableTo( entityType( f.getType() ) ) ) {
AnnotatedFieldDescription annotatedF = new AnnotatedFieldDescription( f );
if ( context.isPersistentField( annotatedF )
&& target.getName().equals( getMappedByNotManyToMany( annotatedF ) )
&& target.getDeclaringType().asErasure().isAssignableTo( entityType( annotatedF.getType() ) ) ) {
log.debugf(
"mappedBy association for field [%s#%s] is [%s#%s]",
target.getDeclaringType().asErasure().getName(),

View File

@ -6,10 +6,9 @@
*/
package org.hibernate.bytecode.enhance.internal.bytebuddy;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedField;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.type.TypeDescription;
class ByteBuddyEnhancementContext {
@ -36,10 +35,6 @@ class ByteBuddyEnhancementContext {
return enhancementContext.isMappedSuperclassClass( new UnloadedTypeDescription( classDescriptor ) );
}
public boolean doBiDirectionalAssociationManagement(FieldDescription field) {
return enhancementContext.doBiDirectionalAssociationManagement( new UnloadedFieldDescription( field ) );
}
public boolean doDirtyCheckingInline(TypeDescription classDescriptor) {
return enhancementContext.doDirtyCheckingInline( new UnloadedTypeDescription( classDescriptor ) );
}
@ -52,28 +47,23 @@ class ByteBuddyEnhancementContext {
return enhancementContext.hasLazyLoadableAttributes( new UnloadedTypeDescription( classDescriptor ) );
}
public boolean isPersistentField(FieldDescription ctField) {
return enhancementContext.isPersistentField( new UnloadedFieldDescription( ctField ) );
public boolean isPersistentField(AnnotatedFieldDescription field) {
return enhancementContext.isPersistentField( field );
}
public FieldDescription[] order(FieldDescription[] persistentFields) {
UnloadedField[] unloadedFields = new UnloadedField[persistentFields.length];
for ( int i = 0; i < unloadedFields.length; i++ ) {
unloadedFields[i] = new UnloadedFieldDescription( persistentFields[i] );
}
UnloadedField[] ordered = enhancementContext.order( unloadedFields );
FieldDescription[] orderedFields = new FieldDescription[persistentFields.length];
for ( int i = 0; i < orderedFields.length; i++ ) {
orderedFields[i] = ( (UnloadedFieldDescription) ordered[i] ).fieldDescription;
}
return orderedFields;
public AnnotatedFieldDescription[] order(AnnotatedFieldDescription[] persistentFields) {
return (AnnotatedFieldDescription[]) enhancementContext.order( persistentFields );
}
public boolean isLazyLoadable(FieldDescription field) {
return enhancementContext.isLazyLoadable( new UnloadedFieldDescription( field ) );
public boolean isLazyLoadable(AnnotatedFieldDescription field) {
return enhancementContext.isLazyLoadable( field );
}
public boolean isMappedCollection(FieldDescription field) {
return enhancementContext.isMappedCollection( new UnloadedFieldDescription( field ) );
public boolean isMappedCollection(AnnotatedFieldDescription field) {
return enhancementContext.isMappedCollection( field );
}
public boolean doBiDirectionalAssociationManagement(AnnotatedFieldDescription field) {
return enhancementContext.doBiDirectionalAssociationManagement( field );
}
}

View File

@ -28,6 +28,7 @@ import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.bytecode.enhance.spi.EnhancementException;
import org.hibernate.bytecode.enhance.spi.Enhancer;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.bytecode.enhance.spi.UnloadedField;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState;
import org.hibernate.engine.spi.CompositeOwner;
@ -46,13 +47,16 @@ import org.hibernate.internal.CoreMessageLogger;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationList;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldDescription.InDefinedShape;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.modifier.FieldPersistence;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeDescription.Generic;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.MethodGraph;
@ -60,6 +64,7 @@ import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.StubMethod;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.pool.TypePool;
public class EnhancerImpl implements Enhancer {
@ -182,7 +187,9 @@ public class EnhancerImpl implements Enhancer {
builder = addInterceptorHandling( builder, managedCtClass );
if ( enhancementContext.doDirtyCheckingInline( managedCtClass ) ) {
if ( collectCollectionFields( managedCtClass ).isEmpty() ) {
List<AnnotatedFieldDescription> collectionFields = collectCollectionFields( managedCtClass );
if ( collectionFields.isEmpty() ) {
builder = builder.implement( SelfDirtinessTracker.class )
.defineField( EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldPersistence.TRANSIENT, Visibility.PRIVATE )
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
@ -223,38 +230,38 @@ public class EnhancerImpl implements Enhancer {
.intercept( FieldAccessor.ofField( EnhancerConstants.TRACKER_COLLECTION_NAME ) );
Implementation isDirty = StubMethod.INSTANCE, getDirtyNames = StubMethod.INSTANCE, clearDirtyNames = StubMethod.INSTANCE;
for ( FieldDescription collectionField : collectCollectionFields( managedCtClass ) ) {
for ( AnnotatedFieldDescription collectionField : collectionFields ) {
if ( collectionField.getType().asErasure().isAssignableTo( Map.class ) ) {
isDirty = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
.bind( CodeTemplates.FieldValue.class, collectionField )
.bind( CodeTemplates.FieldValue.class, collectionField.getFieldDescription() )
.to( CodeTemplates.MapAreCollectionFieldsDirty.class, adviceLocator )
.wrap( isDirty );
getDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
.bind( CodeTemplates.FieldValue.class, collectionField )
.bind( CodeTemplates.FieldValue.class, collectionField.getFieldDescription() )
.to( CodeTemplates.MapGetCollectionFieldDirtyNames.class, adviceLocator )
.wrap( getDirtyNames );
clearDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
.bind( CodeTemplates.FieldValue.class, collectionField )
.bind( CodeTemplates.FieldValue.class, collectionField.getFieldDescription() )
.to( CodeTemplates.MapGetCollectionClearDirtyNames.class, adviceLocator )
.wrap( clearDirtyNames );
}
else {
isDirty = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
.bind( CodeTemplates.FieldValue.class, collectionField )
.bind( CodeTemplates.FieldValue.class, collectionField.getFieldDescription() )
.to( CodeTemplates.CollectionAreCollectionFieldsDirty.class, adviceLocator )
.wrap( isDirty );
getDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
.bind( CodeTemplates.FieldValue.class, collectionField )
.bind( CodeTemplates.FieldValue.class, collectionField.getFieldDescription() )
.to( CodeTemplates.CollectionGetCollectionFieldDirtyNames.class, adviceLocator )
.wrap( getDirtyNames );
clearDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
.bind( CodeTemplates.FieldValue.class, collectionField )
.bind( CodeTemplates.FieldValue.class, collectionField.getFieldDescription() )
.to( CodeTemplates.CollectionGetCollectionClearDirtyNames.class, adviceLocator )
.wrap( clearDirtyNames );
}
@ -375,17 +382,18 @@ public class EnhancerImpl implements Enhancer {
.intercept( FieldAccessor.ofField( fieldName ) );
}
private List<FieldDescription> collectCollectionFields(TypeDescription managedCtClass) {
List<FieldDescription> collectionList = new ArrayList<>();
private List<AnnotatedFieldDescription> collectCollectionFields(TypeDescription managedCtClass) {
List<AnnotatedFieldDescription> collectionList = new ArrayList<>();
for ( FieldDescription ctField : managedCtClass.getDeclaredFields() ) {
// skip static fields and skip fields added by enhancement
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) {
continue;
}
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( ctField );
if ( enhancementContext.isPersistentField( annotatedField ) && !enhancementContext.isMappedCollection( annotatedField ) ) {
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
collectionList.add( ctField );
collectionList.add( annotatedField );
}
}
}
@ -399,7 +407,7 @@ public class EnhancerImpl implements Enhancer {
return collectionList;
}
private Collection<FieldDescription> collectInheritCollectionFields(TypeDefinition managedCtClass) {
private Collection<AnnotatedFieldDescription> collectInheritCollectionFields(TypeDefinition managedCtClass) {
TypeDefinition managedCtSuperclass = managedCtClass.getSuperClass();
if ( managedCtSuperclass == null || managedCtSuperclass.represents( Object.class ) ) {
return Collections.emptyList();
@ -408,13 +416,14 @@ public class EnhancerImpl implements Enhancer {
if ( !enhancementContext.isMappedSuperclassClass( managedCtSuperclass.asErasure() ) ) {
return collectInheritCollectionFields( managedCtSuperclass.asErasure() );
}
List<FieldDescription> collectionList = new ArrayList<FieldDescription>();
List<AnnotatedFieldDescription> collectionList = new ArrayList<>();
for ( FieldDescription ctField : managedCtSuperclass.getDeclaredFields() ) {
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( ctField );
if ( enhancementContext.isPersistentField( annotatedField ) && !enhancementContext.isMappedCollection( annotatedField ) ) {
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
collectionList.add( ctField );
collectionList.add( annotatedField );
}
}
}
@ -427,41 +436,15 @@ public class EnhancerImpl implements Enhancer {
return Character.toUpperCase( value.charAt( 0 ) ) + value.substring( 1 );
}
static boolean isAnnotationPresent(FieldDescription fieldDescription, Class<? extends Annotation> type) {
return getAnnotation( fieldDescription, type ) != null;
}
static <T extends Annotation> AnnotationDescription.Loadable<T> getAnnotation(FieldDescription fieldDescription, Class<T> type) {
AnnotationDescription.Loadable<Access> access = fieldDescription.getDeclaringType().asErasure().getDeclaredAnnotations().ofType( Access.class );
if ( access != null && access.loadSilent().value() == AccessType.PROPERTY ) {
MethodDescription getter = getterOf( fieldDescription );
if ( getter == null ) {
return fieldDescription.getDeclaredAnnotations().ofType( type );
}
else {
return getter.getDeclaredAnnotations().ofType( type );
}
}
else if ( access != null && access.loadSilent().value() == AccessType.FIELD ) {
return fieldDescription.getDeclaredAnnotations().ofType( type );
}
else {
MethodDescription getter = getterOf( fieldDescription );
if ( getter != null ) {
AnnotationDescription.Loadable<T> annotationDescription = getter.getDeclaredAnnotations().ofType( type );
if ( annotationDescription != null ) {
return annotationDescription;
}
}
return fieldDescription.getDeclaredAnnotations().ofType( type );
}
static MethodDescription getterOf(AnnotatedFieldDescription persistentField) {
return getterOf( persistentField.fieldDescription );
}
static MethodDescription getterOf(FieldDescription persistentField) {
MethodList<?> methodList = MethodGraph.Compiler.DEFAULT.compile( persistentField.getDeclaringType().asErasure() )
.listNodes()
.asMethodList()
.filter( isGetter(persistentField.getName() ) );
.filter( isGetter( persistentField.getName() ) );
if ( methodList.size() == 1 ) {
return methodList.getOnly();
}
@ -469,4 +452,88 @@ public class EnhancerImpl implements Enhancer {
return null;
}
}
static class AnnotatedFieldDescription implements UnloadedField {
private final FieldDescription fieldDescription;
private AnnotationList annotations;
AnnotatedFieldDescription(FieldDescription fieldDescription) {
this.fieldDescription = fieldDescription;
}
@Override
public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
return getAnnotations().isAnnotationPresent( annotationType );
}
<T extends Annotation> AnnotationDescription.Loadable<T> getAnnotation(Class<T> annotationType) {
return getAnnotations().ofType( annotationType );
}
String getName() {
return fieldDescription.getName();
}
TypeDefinition getDeclaringType() {
return fieldDescription.getDeclaringType();
}
Generic getType() {
return fieldDescription.getType();
}
InDefinedShape asDefined() {
return fieldDescription.asDefined();
}
String getDescriptor() {
return fieldDescription.getDescriptor();
}
boolean isVisibleTo(TypeDescription typeDescription) {
return fieldDescription.isVisibleTo( typeDescription );
}
FieldDescription getFieldDescription() {
return fieldDescription;
}
private AnnotationList getAnnotations() {
if ( annotations == null ) {
annotations = doGetAnnotations( fieldDescription );
}
return annotations;
}
private static AnnotationList doGetAnnotations(FieldDescription fieldDescription) {
AnnotationDescription.Loadable<Access> access = fieldDescription.getDeclaringType().asErasure()
.getDeclaredAnnotations().ofType( Access.class );
if ( access != null && access.loadSilent().value() == AccessType.PROPERTY ) {
MethodDescription getter = getterOf( fieldDescription );
if ( getter == null ) {
return fieldDescription.getDeclaredAnnotations();
}
else {
return getter.getDeclaredAnnotations();
}
}
else if ( access != null && access.loadSilent().value() == AccessType.FIELD ) {
return fieldDescription.getDeclaredAnnotations();
}
else {
MethodDescription getter = getterOf( fieldDescription );
// Note that the order here is important
List<AnnotationDescription> annotationDescriptions = new ArrayList<>();
if ( getter != null ) {
annotationDescriptions.addAll( getter.getDeclaredAnnotations() );
}
annotationDescriptions.addAll( fieldDescription.getDeclaredAnnotations() );
return fieldDescription.getDeclaredAnnotations();
}
}
}
}

View File

@ -6,16 +6,18 @@
*/
package org.hibernate.bytecode.enhance.internal.bytebuddy;
import static net.bytebuddy.matcher.ElementMatchers.hasDescriptor;
import static net.bytebuddy.matcher.ElementMatchers.named;
import javax.persistence.Id;
import net.bytebuddy.description.method.MethodList;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancementException;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
@ -25,9 +27,6 @@ import net.bytebuddy.jar.asm.Opcodes;
import net.bytebuddy.jar.asm.Type;
import net.bytebuddy.pool.TypePool;
import static net.bytebuddy.matcher.ElementMatchers.hasDescriptor;
import static net.bytebuddy.matcher.ElementMatchers.named;
import java.util.Objects;
final class FieldAccessEnhancer implements AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper {
@ -63,13 +62,13 @@ final class FieldAccessEnhancer implements AsmVisitorWrapper.ForDeclaredMethods.
return;
}
FieldDescription field = findField( owner, name, desc );
AnnotatedFieldDescription field = findField( owner, name, desc );
if ( ( enhancementContext.isEntityClass( field.getDeclaringType().asErasure() )
|| enhancementContext.isCompositeClass( field.getDeclaringType().asErasure() ) )
&& !field.getType().asErasure().equals( managedCtClass )
&& enhancementContext.isPersistentField( field )
&& !EnhancerImpl.isAnnotationPresent( field, Id.class )
&& !field.hasAnnotation( Id.class )
&& !field.getName().equals( "this$0" ) ) {
log.debugf(
@ -110,7 +109,7 @@ final class FieldAccessEnhancer implements AsmVisitorWrapper.ForDeclaredMethods.
};
}
private FieldDescription findField(String owner, String name, String desc) {
private AnnotatedFieldDescription findField(String owner, String name, String desc) {
//Classpool#describe does not accept '/' in the description name as it expects a class name
final String cleanedOwner = owner.replace( '/', '.' );
final TypePool.Resolution resolution = classPool.describe( cleanedOwner );
@ -130,7 +129,7 @@ final class FieldAccessEnhancer implements AsmVisitorWrapper.ForDeclaredMethods.
);
throw new EnhancementException( msg );
}
return fields.getOnly();
return new AnnotatedFieldDescription( fields.getOnly() );
}
@Override

View File

@ -8,6 +8,7 @@ package org.hibernate.bytecode.enhance.internal.bytebuddy;
import java.util.Objects;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
@ -26,17 +27,17 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
protected final TypeDescription managedCtClass;
protected final FieldDescription persistentField;
protected final AnnotatedFieldDescription persistentField;
protected final FieldDescription.InDefinedShape persistentFieldAsDefined;
private FieldReaderAppender(TypeDescription managedCtClass, FieldDescription persistentField) {
private FieldReaderAppender(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
this.managedCtClass = managedCtClass;
this.persistentField = persistentField;
this.persistentFieldAsDefined = persistentField.asDefined();
}
static ByteCodeAppender of(TypeDescription managedCtClass, FieldDescription persistentField) {
static ByteCodeAppender of(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
if ( !persistentField.isVisibleTo( managedCtClass ) ) {
return new MethodDispatching( managedCtClass, persistentField );
}
@ -119,7 +120,7 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
private static class FieldWriting extends FieldReaderAppender {
private FieldWriting(TypeDescription managedCtClass, FieldDescription persistentField) {
private FieldWriting(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
super( managedCtClass, persistentField );
}
@ -146,7 +147,7 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
private static class MethodDispatching extends FieldReaderAppender {
private MethodDispatching(TypeDescription managedCtClass, FieldDescription persistentField) {
private MethodDispatching(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
super( managedCtClass, persistentField );
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.bytecode.enhance.internal.bytebuddy;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
@ -31,7 +32,7 @@ abstract class FieldWriterAppender implements ByteCodeAppender {
this.persistentFieldAsDefined = persistentFieldAsDefined;
}
static ByteCodeAppender of(TypeDescription managedCtClass, FieldDescription persistentField) {
static ByteCodeAppender of(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
if ( !persistentField.isVisibleTo( managedCtClass ) ) {
return new MethodDispatching( managedCtClass, persistentField.asDefined() );
}

View File

@ -8,10 +8,12 @@ package org.hibernate.bytecode.enhance.internal.bytebuddy;
import java.util.Collection;
import java.util.Objects;
import javax.persistence.Embedded;
import javax.persistence.EmbeddedId;
import javax.persistence.Id;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import net.bytebuddy.ClassFileVersion;
@ -44,25 +46,26 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
static Implementation wrap(
TypeDescription managedCtClass,
ByteBuddyEnhancementContext enhancementContext,
FieldDescription persistentField,
AnnotatedFieldDescription persistentField,
Implementation implementation) {
if ( enhancementContext.doDirtyCheckingInline( managedCtClass ) ) {
if ( enhancementContext.isCompositeClass( managedCtClass ) ) {
implementation = Advice.to( CodeTemplates.CompositeDirtyCheckingHandler.class ).wrap( implementation );
}
else if ( !EnhancerImpl.isAnnotationPresent( persistentField, Id.class )
&& !EnhancerImpl.isAnnotationPresent( persistentField, EmbeddedId.class )
else if ( !persistentField.hasAnnotation( Id.class )
&& !persistentField.hasAnnotation( EmbeddedId.class )
&& !( persistentField.getType().asErasure().isAssignableTo( Collection.class )
&& enhancementContext.isMappedCollection( persistentField ) ) ) {
implementation = new InlineDirtyCheckingHandler( implementation, managedCtClass, persistentField.asDefined() );
implementation = new InlineDirtyCheckingHandler( implementation, managedCtClass,
persistentField.asDefined() );
}
if ( enhancementContext.isCompositeClass( persistentField.getType().asErasure() )
&& EnhancerImpl.isAnnotationPresent( persistentField, Embedded.class ) ) {
&& persistentField.hasAnnotation( Embedded.class ) ) {
implementation = Advice.withCustomMapping()
.bind( CodeTemplates.FieldValue.class, persistentField )
.bind( CodeTemplates.FieldValue.class, persistentField.getFieldDescription() )
.bind( CodeTemplates.FieldName.class, persistentField.getName() )
.to( CodeTemplates.CompositeFieldDirtyCheckingHandler.class )
.wrap( implementation );

View File

@ -6,6 +6,9 @@
*/
package org.hibernate.bytecode.enhance.internal.bytebuddy;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.not;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -15,14 +18,12 @@ import java.util.Objects;
import javax.persistence.Embedded;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodList;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.engine.spi.CompositeOwner;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.field.FieldDescription;
@ -40,9 +41,6 @@ import net.bytebuddy.jar.asm.Opcodes;
import net.bytebuddy.jar.asm.Type;
import net.bytebuddy.pool.TypePool;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.not;
final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper {
private static final CoreMessageLogger log = CoreLogging.messageLogger( PersistentAttributeTransformer.class );
@ -53,13 +51,13 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
private final TypePool classPool;
private final FieldDescription[] enhancedFields;
private final AnnotatedFieldDescription[] enhancedFields;
private PersistentAttributeTransformer(
TypeDescription managedCtClass,
ByteBuddyEnhancementContext enhancementContext,
TypePool classPool,
FieldDescription[] enhancedFields) {
AnnotatedFieldDescription[] enhancedFields) {
this.managedCtClass = managedCtClass;
this.enhancementContext = enhancementContext;
this.classPool = classPool;
@ -70,14 +68,15 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
TypeDescription managedCtClass,
ByteBuddyEnhancementContext enhancementContext,
TypePool classPool) {
List<FieldDescription> persistentFieldList = new ArrayList<FieldDescription>();
List<AnnotatedFieldDescription> persistentFieldList = new ArrayList<>();
for ( FieldDescription ctField : managedCtClass.getDeclaredFields() ) {
// skip static fields and skip fields added by enhancement and outer reference in inner classes
if ( ctField.getName().startsWith( "$$_hibernate_" ) || "this$0".equals( ctField.getName() ) ) {
continue;
}
if ( !ctField.isStatic() && enhancementContext.isPersistentField( ctField ) ) {
persistentFieldList.add( ctField );
AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( ctField );
if ( !ctField.isStatic() && enhancementContext.isPersistentField( annotatedField ) ) {
persistentFieldList.add( annotatedField );
}
}
// HHH-10646 Add fields inherited from @MappedSuperclass
@ -86,12 +85,12 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
persistentFieldList.addAll( collectInheritPersistentFields( managedCtClass, enhancementContext ) );
}
FieldDescription[] orderedFields = enhancementContext.order( persistentFieldList.toArray( new FieldDescription[0] ) );
AnnotatedFieldDescription[] orderedFields = enhancementContext.order( persistentFieldList.toArray( new AnnotatedFieldDescription[0] ) );
log.debugf( "Persistent fields for entity %s: %s", managedCtClass.getName(), Arrays.toString( orderedFields ) );
return new PersistentAttributeTransformer( managedCtClass, enhancementContext, classPool, orderedFields );
}
private static Collection<FieldDescription> collectInheritPersistentFields(
private static Collection<AnnotatedFieldDescription> collectInheritPersistentFields(
TypeDefinition managedCtClass,
ByteBuddyEnhancementContext enhancementContext) {
if ( managedCtClass == null || managedCtClass.represents( Object.class ) ) {
@ -102,15 +101,18 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
if ( !enhancementContext.isMappedSuperclassClass( managedCtSuperclass.asErasure() ) ) {
return collectInheritPersistentFields( managedCtSuperclass, enhancementContext );
}
log.debugf( "Found @MappedSuperclass %s to collectPersistenceFields", managedCtSuperclass );
List<FieldDescription> persistentFieldList = new ArrayList<FieldDescription>();
List<AnnotatedFieldDescription> persistentFieldList = new ArrayList<>();
for ( FieldDescription ctField : managedCtSuperclass.getDeclaredFields() ) {
if ( ctField.getName().startsWith( "$$_hibernate_" ) || "this$0".equals( ctField.getName() ) ) {
continue;
}
if ( !ctField.isStatic() && enhancementContext.isPersistentField( ctField ) ) {
persistentFieldList.add( ctField );
AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( ctField );
if ( !ctField.isStatic() && enhancementContext.isPersistentField( annotatedField ) ) {
persistentFieldList.add( annotatedField );
}
}
persistentFieldList.addAll( collectInheritPersistentFields( managedCtSuperclass, enhancementContext ) );
@ -157,7 +159,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
}
private boolean isEnhanced(String owner, String name, String desc) {
for ( FieldDescription enhancedField : enhancedFields ) {
for ( AnnotatedFieldDescription enhancedField : enhancedFields ) {
if ( enhancedField.getName().equals( name )
&& enhancedField.getDescriptor().equals( desc )
&& enhancedField.getDeclaringType().asErasure().getInternalName().equals( owner ) ) {
@ -171,7 +173,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
boolean compositeOwner = false;
builder = builder.visit( new AsmVisitorWrapper.ForDeclaredMethods().invokable( not( nameStartsWith( "$$_hibernate_" ) ), this ) );
for ( FieldDescription enhancedField : enhancedFields ) {
for ( AnnotatedFieldDescription enhancedField : enhancedFields ) {
builder = builder
.defineMethod(
EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + enhancedField.getName(),
@ -195,7 +197,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
if ( !compositeOwner
&& !accessor
&& EnhancerImpl.isAnnotationPresent( enhancedField, Embedded.class )
&& enhancedField.hasAnnotation( Embedded.class )
&& enhancementContext.isCompositeClass( enhancedField.getType().asErasure() )
&& enhancementContext.doDirtyCheckingInline( managedCtClass ) ) {
compositeOwner = true;
@ -219,7 +221,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
return builder;
}
private Implementation fieldReader(FieldDescription enhancedField) {
private Implementation fieldReader(AnnotatedFieldDescription enhancedField) {
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass ) || !enhancementContext.isLazyLoadable( enhancedField ) ) {
if ( enhancedField.getDeclaringType().asErasure().equals( managedCtClass ) ) {
return FieldAccessor.ofField( enhancedField.getName() ).in( enhancedField.getDeclaringType().asErasure() );
@ -233,7 +235,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
}
}
private Implementation fieldWriter(FieldDescription enhancedField) {
private Implementation fieldWriter(AnnotatedFieldDescription enhancedField) {
Implementation implementation;
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass ) || !enhancementContext.isLazyLoadable( enhancedField ) ) {
if ( enhancedField.getDeclaringType().asErasure().equals( managedCtClass ) ) {
@ -259,9 +261,9 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
private final TypeDescription managedCtClass;
private final FieldDescription persistentField;
private final AnnotatedFieldDescription persistentField;
private FieldMethodReader(TypeDescription managedCtClass, FieldDescription persistentField) {
private FieldMethodReader(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
this.managedCtClass = managedCtClass;
this.persistentField = persistentField;
}
@ -289,9 +291,9 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
private final TypeDescription managedCtClass;
private final FieldDescription persistentField;
private final AnnotatedFieldDescription persistentField;
private FieldMethodWriter(TypeDescription managedCtClass, FieldDescription persistentField) {
private FieldMethodWriter(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
this.managedCtClass = managedCtClass;
this.persistentField = persistentField;
}

View File

@ -1,27 +0,0 @@
/*
* 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.bytecode.enhance.internal.bytebuddy;
import java.lang.annotation.Annotation;
import org.hibernate.bytecode.enhance.spi.UnloadedField;
import net.bytebuddy.description.field.FieldDescription;
class UnloadedFieldDescription implements UnloadedField {
final FieldDescription fieldDescription;
UnloadedFieldDescription(FieldDescription fieldDescription) {
this.fieldDescription = fieldDescription;
}
@Override
public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
return fieldDescription.getDeclaredAnnotations().isAnnotationPresent( annotationType );
}
}

View File

@ -9,7 +9,6 @@ package org.hibernate.bytecode.enhance.internal.bytebuddy;
import java.lang.annotation.Annotation;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.bytecode.enhance.spi.UnloadedField;
import net.bytebuddy.description.type.TypeDescription;