You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2021/03/24 14:03:30 UTC
[cayenne] branch master updated: CAY-2705 Performance of callback
annotation processing
This is an automated email from the ASF dual-hosted git repository.
ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
The following commit(s) were added to refs/heads/master by this push:
new 54d7728 CAY-2705 Performance of callback annotation processing
54d7728 is described below
commit 54d7728873ac0f0646d07a794c97f1685fe5dd93
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Wed Mar 24 15:56:14 2021 +0300
CAY-2705 Performance of callback annotation processing
---
RELEASE-NOTES.txt | 1 +
.../org/apache/cayenne/map/EntityResolver.java | 2 +-
.../apache/cayenne/reflect/CallbackOnEntity.java | 65 +++++++++++-----------
.../reflect/LifecycleCallbackEventHandler.java | 9 +++
.../cayenne/reflect/LifecycleCallbackRegistry.java | 18 +++++-
5 files changed, 60 insertions(+), 35 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 66815b1..f8ed0ac 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -16,6 +16,7 @@ Changes/New Features:
Bug Fixes:
CAY-2702 Modeler: Callbacks table has too small default width
+CAY-2705 Performance of callback annotation processing
----------------------------------
Release: 4.2.M3
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
index 0d498a3..b62bfa3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
@@ -176,7 +176,7 @@ public class EntityResolver implements MappingNamespace, Serializable {
for (Method m : entityClass.getDeclaredMethods()) {
LIFECYCLE_EVENT_MAP.forEach((eventType, annotationType) -> {
if(m.getDeclaredAnnotation(annotationType) != null) {
- callbackRegistry.addCallback(eventType, entityClass, m.getName());
+ callbackRegistry.addCallback(eventType, entityClass, m);
}
});
}
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/CallbackOnEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/CallbackOnEntity.java
index 610217a..ecf5f82 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/CallbackOnEntity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/CallbackOnEntity.java
@@ -33,19 +33,31 @@ import org.apache.cayenne.util.Util;
*/
class CallbackOnEntity extends AbstractCallback {
- private Method callbackMethod;
+ private final Method callbackMethod;
- CallbackOnEntity(Class<?> objectClass, String methodName)
- throws IllegalArgumentException {
- this.callbackMethod = findMethod(objectClass, methodName);
+ CallbackOnEntity(Class<?> objectClass, String methodName) throws IllegalArgumentException {
+ this(findMethod(objectClass, methodName));
+ }
+
+ /**
+ * @since 4.2
+ */
+ CallbackOnEntity(Method method) throws IllegalArgumentException {
+ if(!validateMethod(method)) {
+ throw new IllegalArgumentException("Class " + method.getDeclaringClass().getName()
+ + " has no valid callback method '" + method.getName() + "'");
+ }
+ this.callbackMethod = method;
+ if (!Util.isAccessible(callbackMethod)) {
+ callbackMethod.setAccessible(true);
+ }
}
@Override
public void performCallback(Object entity) {
try {
callbackMethod.invoke(entity, (Object[]) null);
- }
- catch (Exception e) {
+ } catch (Exception e) {
throw new CayenneRuntimeException("Error invoking entity callback method "
+ callbackMethod.getName(), e);
}
@@ -59,32 +71,23 @@ class CallbackOnEntity extends AbstractCallback {
+ callbackMethod.getName();
}
- private Method findMethod(Class<?> objectClass, String methodName)
- throws IllegalArgumentException {
- Method[] methods = objectClass.getDeclaredMethods();
- for (Method method : methods) {
- if (methodName.equals(method.getName())) {
-
- // must be non-static, void, with no args
- // JPA spec also requires it to be non-final, but we don't care
- int modifiers = method.getModifiers();
- if (!Modifier.isStatic(modifiers)
- && Void.TYPE.isAssignableFrom(method.getReturnType())
- && method.getParameterTypes().length == 0) {
-
- if (!Util.isAccessible(method)) {
- method.setAccessible(true);
- }
+ static private boolean validateMethod(Method method) {
+ int modifiers = method.getModifiers();
+ // must be non-static, void, with no args
+ // JPA spec also requires it to be non-final, but we don't care
+ return !Modifier.isStatic(modifiers)
+ && Void.TYPE.isAssignableFrom(method.getReturnType())
+ && method.getParameterTypes().length == 0;
+ }
- return method;
- }
- }
+ static private Method findMethod(Class<?> objectClass, String methodName) throws IllegalArgumentException {
+ Method method;
+ try {
+ method = objectClass.getDeclaredMethod(methodName);
+ } catch (NoSuchMethodException ex) {
+ throw new IllegalArgumentException("Class " + objectClass.getName()
+ + " has no valid callback method '" + methodName + "'");
}
-
- throw new IllegalArgumentException("Class "
- + objectClass.getName()
- + " has no valid callback method '"
- + methodName
- + "'");
+ return method;
}
}
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
index 28b478f..9dd4147 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
@@ -87,6 +87,15 @@ class LifecycleCallbackEventHandler {
}
/**
+ * Registers a callback method to be invoked on an entity class instances when a
+ * lifecycle event occurs.
+ * @since 4.2
+ */
+ void addListener(Class<?> entityClass, Method method) {
+ addCallback(entityClass, new CallbackOnEntity(method));
+ }
+
+ /**
* Registers callback method to be invoked on a provided non-entity object when a
* lifecycle event occurs.
*/
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java
index d730db6..c8af4c8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java
@@ -64,9 +64,7 @@ public class LifecycleCallbackRegistry {
this.entityResolver = resolver;
- // initialize callbacks map in constructor to avoid synchronization
- // issues
- // downstream.
+ // initialize callbacks map in constructor to avoid synchronization issues downstream.
this.eventCallbacks = new LifecycleCallbackEventHandler[LifecycleEvent.values().length];
for (int i = 0; i < eventCallbacks.length; i++) {
eventCallbacks[i] = new LifecycleCallbackEventHandler();
@@ -161,6 +159,20 @@ public class LifecycleCallbackRegistry {
}
/**
+ * Registers a callback method to be invoked on an entity class instances
+ * when a lifecycle event occurs.
+ *
+ * @param type of the lifecycle event
+ * @param entityClass type of the entity
+ * @param method callback method reference
+ *
+ * @since 4.2
+ */
+ public void addCallback(LifecycleEvent type, Class<?> entityClass, Method method) {
+ eventCallbacks[type.ordinal()].addListener(entityClass, method);
+ }
+
+ /**
* Adds a listener, mapping its methods to events based on annotations.
*
* @since 3.1