diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java index cebd93a2a9..ff167509f9 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java @@ -7,7 +7,6 @@ package org.hibernate.event.service.internal; import java.lang.reflect.Array; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -80,11 +79,11 @@ import static org.hibernate.event.spi.EventType.UPDATE; public class EventListenerRegistryImpl implements EventListenerRegistry { private Map listenerClassToInstanceMap = new HashMap(); - private Map registeredEventListenersMap = prepareListenerMap(); + private EventListenerGroupImpl[] registeredEventListeners = prepareListenerAssociation(); @SuppressWarnings({ "unchecked" }) public EventListenerGroupImpl getEventListenerGroup(EventType eventType) { - EventListenerGroupImpl listeners = registeredEventListenersMap.get( eventType ); + EventListenerGroupImpl listeners = registeredEventListeners[ eventType.ordinal() ]; if ( listeners == null ) { throw new HibernateException( "Unable to find listeners for type [" + eventType.eventName() + "]" ); } @@ -93,8 +92,10 @@ public class EventListenerRegistryImpl implements EventListenerRegistry { @Override public void addDuplicationStrategy(DuplicationStrategy strategy) { - for ( EventListenerGroupImpl group : registeredEventListenersMap.values() ) { - group.addDuplicationStrategy( strategy ); + for ( EventListenerGroupImpl group : registeredEventListeners ) { + if ( group != null ) { + group.addDuplicationStrategy( strategy ); + } } } @@ -165,252 +166,252 @@ public class EventListenerRegistryImpl implements EventListenerRegistry { getEventListenerGroup( type ).prependListeners( listeners ); } - private static Map prepareListenerMap() { - final Map workMap = new HashMap(); + private static EventListenerGroupImpl[] prepareListenerAssociation() { + EventListenerGroupImpl[] listenerArray = new EventListenerGroupImpl[ EventType.values().size() ]; // auto-flush listeners prepareListeners( AUTO_FLUSH, new DefaultAutoFlushEventListener(), - workMap + listenerArray ); // create listeners prepareListeners( PERSIST, new DefaultPersistEventListener(), - workMap + listenerArray ); // create-onflush listeners prepareListeners( PERSIST_ONFLUSH, new DefaultPersistOnFlushEventListener(), - workMap + listenerArray ); // delete listeners prepareListeners( DELETE, new DefaultDeleteEventListener(), - workMap + listenerArray ); // dirty-check listeners prepareListeners( DIRTY_CHECK, new DefaultDirtyCheckEventListener(), - workMap + listenerArray ); // evict listeners prepareListeners( EVICT, new DefaultEvictEventListener(), - workMap + listenerArray ); prepareListeners( CLEAR, - workMap + listenerArray ); // flush listeners prepareListeners( FLUSH, new DefaultFlushEventListener(), - workMap + listenerArray ); // flush-entity listeners prepareListeners( FLUSH_ENTITY, new DefaultFlushEntityEventListener(), - workMap + listenerArray ); // load listeners prepareListeners( LOAD, new DefaultLoadEventListener(), - workMap + listenerArray ); // resolve natural-id listeners prepareListeners( RESOLVE_NATURAL_ID, new DefaultResolveNaturalIdEventListener(), - workMap + listenerArray ); // load-collection listeners prepareListeners( INIT_COLLECTION, new DefaultInitializeCollectionEventListener(), - workMap + listenerArray ); // lock listeners prepareListeners( LOCK, new DefaultLockEventListener(), - workMap + listenerArray ); // merge listeners prepareListeners( MERGE, new DefaultMergeEventListener(), - workMap + listenerArray ); // pre-collection-recreate listeners prepareListeners( PRE_COLLECTION_RECREATE, - workMap + listenerArray ); // pre-collection-remove listeners prepareListeners( PRE_COLLECTION_REMOVE, - workMap + listenerArray ); // pre-collection-update listeners prepareListeners( PRE_COLLECTION_UPDATE, - workMap + listenerArray ); // pre-delete listeners prepareListeners( PRE_DELETE, - workMap + listenerArray ); // pre-insert listeners prepareListeners( PRE_INSERT, - workMap + listenerArray ); // pre-load listeners prepareListeners( PRE_LOAD, new DefaultPreLoadEventListener(), - workMap + listenerArray ); // pre-update listeners prepareListeners( PRE_UPDATE, - workMap + listenerArray ); // post-collection-recreate listeners prepareListeners( POST_COLLECTION_RECREATE, - workMap + listenerArray ); // post-collection-remove listeners prepareListeners( POST_COLLECTION_REMOVE, - workMap + listenerArray ); // post-collection-update listeners prepareListeners( POST_COLLECTION_UPDATE, - workMap + listenerArray ); // post-commit-delete listeners prepareListeners( POST_COMMIT_DELETE, - workMap + listenerArray ); // post-commit-insert listeners prepareListeners( POST_COMMIT_INSERT, - workMap + listenerArray ); // post-commit-update listeners prepareListeners( POST_COMMIT_UPDATE, - workMap + listenerArray ); // post-delete listeners prepareListeners( POST_DELETE, - workMap + listenerArray ); // post-insert listeners prepareListeners( POST_INSERT, - workMap + listenerArray ); // post-load listeners prepareListeners( POST_LOAD, new DefaultPostLoadEventListener(), - workMap + listenerArray ); // post-update listeners prepareListeners( POST_UPDATE, - workMap + listenerArray ); // update listeners prepareListeners( UPDATE, new DefaultUpdateEventListener(), - workMap + listenerArray ); // refresh listeners prepareListeners( REFRESH, new DefaultRefreshEventListener(), - workMap + listenerArray ); // replicate listeners prepareListeners( REPLICATE, new DefaultReplicateEventListener(), - workMap + listenerArray ); // save listeners prepareListeners( SAVE, new DefaultSaveEventListener(), - workMap + listenerArray ); // save-update listeners prepareListeners( SAVE_UPDATE, new DefaultSaveOrUpdateEventListener(), - workMap + listenerArray ); - return Collections.unmodifiableMap( workMap ); + return listenerArray; } - private static void prepareListeners(EventType type, Map map) { - prepareListeners( type, null, map ); + private static void prepareListeners(EventType type, EventListenerGroupImpl[] listenerArray) { + prepareListeners( type, null, listenerArray ); } - private static void prepareListeners(EventType type, T defaultListener, Map map) { + private static void prepareListeners(EventType type, T defaultListener, EventListenerGroupImpl[] listenerArray) { final EventListenerGroupImpl listenerGroup; if ( type == EventType.POST_COMMIT_DELETE || type == EventType.POST_COMMIT_INSERT @@ -424,7 +425,7 @@ public class EventListenerRegistryImpl implements EventListenerRegistry { if ( defaultListener != null ) { listenerGroup.appendListener( defaultListener ); } - map.put( type, listenerGroup ); + listenerArray[ type.ordinal() ] = listenerGroup; } } diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/EventType.java b/hibernate-core/src/main/java/org/hibernate/event/spi/EventType.java index 8ac74d948f..0a5171204c 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/spi/EventType.java +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/EventType.java @@ -12,6 +12,7 @@ import java.security.PrivilegedAction; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import org.hibernate.HibernateException; @@ -20,7 +21,10 @@ import org.hibernate.HibernateException; * * @author Steve Ebersole */ -public class EventType { +public final class EventType { + + private static AtomicInteger typeCounter = new AtomicInteger( 0 ); + public static final EventType LOAD = create( "load", LoadEventListener.class ); public static final EventType RESOLVE_NATURAL_ID = create( "resolve-natural-id", ResolveNaturalIdEventListener.class ); @@ -131,13 +135,14 @@ public class EventType { return EVENT_TYPE_BY_NAME_MAP.values(); } - private final String eventName; private final Class baseListenerInterface; + private final int ordinal; private EventType(String eventName, Class baseListenerInterface) { this.eventName = eventName; this.baseListenerInterface = baseListenerInterface; + this.ordinal = typeCounter.getAndIncrement(); } public String eventName() { @@ -152,4 +157,17 @@ public class EventType { public String toString() { return eventName(); } + + /** + * EventType is effectively an enumeration. Since there is a known, limited number of possible types, we expose an + * ordinal for each in order to be able to efficiently do associations elsewhere in the codebase (array vs. Map) + * + * For the total number of types, see {@link #values()} + * + * @return An unique ordinal for this {@link EventType}, starting at 0 and up to the number of distinct events + */ + public int ordinal() { + return ordinal; + } + }