diff --git a/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java b/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java index afaf0e776..5d7922556 100644 --- a/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java +++ b/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java @@ -43,10 +43,14 @@ import org.redisson.command.CommandAsyncExecutor; import org.redisson.command.CommandBatchService; import org.redisson.liveobject.LiveObjectSearch; import org.redisson.liveobject.LiveObjectTemplate; -import org.redisson.liveobject.core.*; +import org.redisson.liveobject.core.AccessorInterceptor; +import org.redisson.liveobject.core.FieldAccessorInterceptor; +import org.redisson.liveobject.core.LiveObjectInterceptor; +import org.redisson.liveobject.core.RMapInterceptor; import org.redisson.liveobject.misc.AdvBeanCopy; import org.redisson.liveobject.misc.ClassUtils; import org.redisson.liveobject.misc.Introspectior; +import org.redisson.liveobject.resolver.MapResolver; import org.redisson.liveobject.resolver.NamingScheme; import org.redisson.liveobject.resolver.RIdResolver; @@ -65,12 +69,14 @@ public class RedissonLiveObjectService implements RLiveObjectService { private final ConcurrentMap, Class> classCache; private final CommandAsyncExecutor commandExecutor; private final LiveObjectSearch seachEngine; + private final MapResolver mapResolver; public RedissonLiveObjectService(ConcurrentMap, Class> classCache, CommandAsyncExecutor commandExecutor) { this.classCache = classCache; this.commandExecutor = commandExecutor; this.seachEngine = new LiveObjectSearch(commandExecutor); + this.mapResolver = new MapResolver(); } private void addExpireListener(CommandAsyncExecutor commandExecutor) { @@ -102,10 +108,10 @@ public class RedissonLiveObjectService implements RLiveObjectService { return Class.forName(className); } catch (ClassNotFoundException e) { return classCache.keySet() - .stream() - .filter(c -> c.getName().equals(className)) - .findAny() - .orElse(null); + .stream() + .filter(c -> c.getName().equals(className)) + .findAny() + .orElse(null); } } @@ -122,7 +128,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { // } private RMap getMap(Object proxied) { - return ClassUtils.getField(proxied, "liveObjectLiveMap"); + return asLiveObject(proxied).getLiveObjectLiveMap(); } private Object generateId(Class entityClass, String idFieldName) throws NoSuchFieldException { @@ -270,7 +276,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { Object object = ClassUtils.getField(detachedObject, field.getName()); if (object == null || object instanceof Collection - || ClassUtils.isAnnotationPresent(object.getClass(), REntity.class)) { + || ClassUtils.isAnnotationPresent(object.getClass(), REntity.class)) { continue; } @@ -285,7 +291,12 @@ public class RedissonLiveObjectService implements RLiveObjectService { batchService.execute(); + detached2Attached.values().forEach(attachedObject -> { + RLiveObject lo = asLiveObject(attachedObject); + mapResolver.remove(attachedObject.getClass().getSuperclass(), lo.getLiveObjectId()); + }); classCache.clear(); + List attachedObjects = new ArrayList<>(); for (Object attachedObject : detached2Attached.values()) { RLiveObject lo = asLiveObject(attachedObject); @@ -414,7 +425,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { if (isLiveObject(instance)) { clazz = clazz.getSuperclass(); } - + RCascade annotation = ClassUtils.getAnnotation(clazz, fieldName, RCascade.class); if (annotation != null) { throw new IllegalArgumentException("RCascade annotation couldn't be defined for non-Redisson object '" + clazz + "' and field '" + fieldName + "'"); @@ -426,7 +437,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { if (isLiveObject(instance)) { clazz = clazz.getSuperclass(); } - + RCascade annotation = ClassUtils.getAnnotation(clazz, fieldName, RCascade.class); if (annotation != null && (Arrays.asList(annotation.value()).contains(type) || Arrays.asList(annotation.value()).contains(RCascadeType.ALL))) { @@ -434,7 +445,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { } return false; } - + @Override public T detach(T attachedObject) { addExpireListener(commandExecutor); @@ -448,15 +459,15 @@ public class RedissonLiveObjectService implements RLiveObjectService { T detached = instantiateDetachedObject((Class) attachedObject.getClass().getSuperclass(), asLiveObject(attachedObject).getLiveObjectId()); new BeanCopy(attachedObject, detached).declared(true).copy(); alreadyDetached.put(getMap(attachedObject).getName(), detached); - + for (Entry obj : getMap(attachedObject).entrySet()) { if (!checkCascade(attachedObject, RCascadeType.DETACH, obj.getKey())) { continue; } - + if (obj.getValue() instanceof RSortedSet) { SortedSet redissonSet = (SortedSet) obj.getValue(); - Set set = new TreeSet(redissonSet.comparator()); + Set set = new TreeSet(redissonSet.comparator()); for (Object object : redissonSet) { if (isLiveObject(object)) { Object detachedObject = alreadyDetached.get(getMap(object).getName()); @@ -467,11 +478,11 @@ public class RedissonLiveObjectService implements RLiveObjectService { } set.add(object); } - + ClassUtils.setField(detached, obj.getKey(), set); } else if (obj.getValue() instanceof RDeque) { Collection redissonDeque = (Collection) obj.getValue(); - Deque deque = new LinkedList(); + Deque deque = new LinkedList(); for (Object object : redissonDeque) { if (isLiveObject(object)) { Object detachedObject = alreadyDetached.get(getMap(object).getName()); @@ -482,11 +493,11 @@ public class RedissonLiveObjectService implements RLiveObjectService { } deque.add(object); } - + ClassUtils.setField(detached, obj.getKey(), deque); } else if (obj.getValue() instanceof RQueue) { Collection redissonQueue = (Collection) obj.getValue(); - Queue queue = new LinkedList(); + Queue queue = new LinkedList(); for (Object object : redissonQueue) { if (isLiveObject(object)) { Object detachedObject = alreadyDetached.get(getMap(object).getName()); @@ -497,10 +508,10 @@ public class RedissonLiveObjectService implements RLiveObjectService { } queue.add(object); } - + ClassUtils.setField(detached, obj.getKey(), queue); } else if (obj.getValue() instanceof RSet) { - Set set = new HashSet(); + Set set = new HashSet(); Collection redissonSet = (Collection) obj.getValue(); for (Object object : redissonSet) { if (isLiveObject(object)) { @@ -512,10 +523,10 @@ public class RedissonLiveObjectService implements RLiveObjectService { } set.add(object); } - + ClassUtils.setField(detached, obj.getKey(), set); } else if (obj.getValue() instanceof RList) { - List list = new ArrayList(); + List list = new ArrayList(); Collection redissonList = (Collection) obj.getValue(); for (Object object : redissonList) { if (isLiveObject(object)) { @@ -536,12 +547,12 @@ public class RedissonLiveObjectService implements RLiveObjectService { } ClassUtils.setField(detached, obj.getKey(), detachedObject); } else if (obj.getValue() instanceof RMap) { - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap(); Map redissonMap = (Map) obj.getValue(); for (Entry entry : redissonMap.entrySet()) { Object key = entry.getKey(); Object value = entry.getValue(); - + if (isLiveObject(key)) { Object detachedObject = alreadyDetached.get(getMap(key).getName()); if (detachedObject == null) { @@ -549,7 +560,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { } key = detachedObject; } - + if (isLiveObject(value)) { Object detachedObject = alreadyDetached.get(getMap(value).getName()); if (detachedObject == null) { @@ -559,16 +570,16 @@ public class RedissonLiveObjectService implements RLiveObjectService { } map.put(key, value); } - + ClassUtils.setField(detached, obj.getKey(), map); } else { validateAnnotation(detached, obj.getKey()); } } - + return detached; } - + @Override public void delete(T attachedObject) { addExpireListener(commandExecutor); @@ -578,12 +589,12 @@ public class RedissonLiveObjectService implements RLiveObjectService { private void delete(T attachedObject, Set deleted) { validateAttached(attachedObject); - + for (Entry obj : getMap(attachedObject).entrySet()) { if (!checkCascade(attachedObject, RCascadeType.DELETE, obj.getKey())) { continue; } - + if (obj.getValue() instanceof RSortedSet) { deleteCollection(deleted, (Iterable) obj.getValue()); ((RObject) obj.getValue()).delete(); @@ -611,7 +622,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { } else { validateAnnotation(attachedObject, obj.getKey()); } - + } asLiveObject(attachedObject).delete(); } @@ -651,7 +662,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { deleteCollections(id, entityClass, ce); RMap liveMap = new RedissonMap<>(namingScheme.getCodec(), commandExecutor, - mapName, null, null, null); + mapName, null, null, null); Map values = liveMap.getAll(fieldNames); for (String fieldName : fieldNames) { Object value = values.get(fieldName); @@ -668,6 +679,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { idsMultimap.removeAsync(value, liveObjectId); } } + mapResolver.remove(entityClass, id); return new RedissonKeys(ce).deleteAsync(mapName); } @@ -683,7 +695,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { TypeDescription.Generic n1 = TypeDescription.Generic.Builder.rawType(Number.class).build(); for (InDefinedShape field : fields) { boolean isNumber = n1.accept(TypeDescription.Generic.Visitor.Assigner.INSTANCE) - .isAssignableFrom(field.getType().asErasure().asBoxed().asGenericType()); + .isAssignableFrom(field.getType().asErasure().asBoxed().asGenericType()); String indexName = namingScheme.getIndexName(entityClass, field.getName()); if (isNumber) { RScoredSortedSetAsync set = new RedissonScoredSortedSet<>(namingScheme.getCodec(), ce, indexName, null); @@ -779,8 +791,10 @@ public class RedissonLiveObjectService implements RLiveObjectService { public void unregisterClass(Class cls) { if (cls.isAssignableFrom(RLiveObject.class)) { classCache.remove(cls.getSuperclass()); + mapResolver.remove(cls.getSuperclass()); } else { classCache.remove(cls); + mapResolver.remove(cls); } } @@ -840,11 +854,11 @@ public class RedissonLiveObjectService implements RLiveObjectService { FieldList fields = Introspectior.getFieldsWithAnnotation(entityClass, RIndex.class); fields = fields.filter(ElementMatchers.fieldType(ElementMatchers.hasSuperType( - ElementMatchers.anyOf(Map.class, Collection.class, RObject.class)))); + ElementMatchers.anyOf(Map.class, Collection.class, RObject.class)))); for (InDefinedShape field : fields) { throw new IllegalArgumentException("RIndex annotation couldn't be defined for field '" + field.getName() + "' with type '" + field.getType() + "'"); } - + FieldList fieldsWithRIdAnnotation = Introspectior.getFieldsWithAnnotation(entityClass, RId.class); if (fieldsWithRIdAnnotation.size() == 0) { @@ -880,7 +894,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { throw new IllegalArgumentException("The object supplied is must be a RLiveObject"); } } - + private Class createProxy(Class entityClass, CommandAsyncExecutor commandExecutor) { DynamicType.Builder builder = new ByteBuddy() .subclass(entityClass); @@ -891,37 +905,32 @@ public class RedissonLiveObjectService implements RLiveObjectService { } Class proxied = builder.method(ElementMatchers.isDeclaredBy( - ElementMatchers.anyOf(RLiveObject.class, RExpirable.class, RObject.class)) - .and(ElementMatchers.isGetter().or(ElementMatchers.isSetter()) - .or(ElementMatchers.named("isPhantom")) - .or(ElementMatchers.named("delete")))) + ElementMatchers.anyOf(RLiveObject.class, RExpirable.class, RObject.class)) + .and(ElementMatchers.isGetter().or(ElementMatchers.isSetter()) + .or(ElementMatchers.named("isPhantom")) + .or(ElementMatchers.named("delete")))) .intercept(MethodDelegation.withDefaultConfiguration() .withBinders(FieldProxy.Binder .install(LiveObjectInterceptor.Getter.class, LiveObjectInterceptor.Setter.class)) - .to(new LiveObjectInterceptor(commandExecutor, this, entityClass, getRIdFieldName(entityClass)))) -// .intercept(MethodDelegation.to( -// new LiveObjectInterceptor(redisson, codecProvider, entityClass, -// getRIdFieldName(entityClass))) -// .appendParameterBinder(FieldProxy.Binder -// .install(LiveObjectInterceptor.Getter.class, -// LiveObjectInterceptor.Setter.class))) + .to(new LiveObjectInterceptor(commandExecutor, this, entityClass, mapResolver))) .implement(RLiveObject.class) + .method(ElementMatchers.isAnnotatedWith(RFieldAccessor.class) .and(ElementMatchers.named("get") - .or(ElementMatchers.named("set")))) + .or(ElementMatchers.named("set")))) .intercept(MethodDelegation.to(FieldAccessorInterceptor.class)) - - .method(ElementMatchers.isDeclaredBy(RExpirable.class) - .or(ElementMatchers.isDeclaredBy(RExpirableAsync.class))) - .intercept(MethodDelegation.to(RExpirableInterceptor.class)) - .implement(RExpirable.class) - + .method(ElementMatchers.isDeclaredBy(Map.class) + .or(ElementMatchers.isDeclaredBy(RExpirable.class)) + .or(ElementMatchers.isDeclaredBy(RExpirableAsync.class)) .or(ElementMatchers.isDeclaredBy(ConcurrentMap.class)) .or(ElementMatchers.isDeclaredBy(RMapAsync.class)) .or(ElementMatchers.isDeclaredBy(RMap.class))) - .intercept(MethodDelegation.to(RMapInterceptor.class)) + .intercept(MethodDelegation.withDefaultConfiguration() + .withBinders(FieldProxy.Binder + .install(LiveObjectInterceptor.Getter.class, + LiveObjectInterceptor.Setter.class)).to(new RMapInterceptor(commandExecutor, entityClass, mapResolver))) .implement(RMap.class) .method(ElementMatchers.not(ElementMatchers.isDeclaredBy(Object.class)) @@ -936,9 +945,13 @@ public class RedissonLiveObjectService implements RLiveObjectService { .or(ElementMatchers.isSetter())) .and(ElementMatchers.isPublic() .or(ElementMatchers.isProtected())) - ) - .intercept(MethodDelegation.to(new AccessorInterceptor(commandExecutor))) - + ) + .intercept(MethodDelegation.withDefaultConfiguration() + .withBinders(FieldProxy.Binder + .install(LiveObjectInterceptor.Getter.class, + LiveObjectInterceptor.Setter.class)) + .to(new AccessorInterceptor(entityClass, commandExecutor, mapResolver))) + .make().load(entityClass.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); diff --git a/redisson/src/main/java/org/redisson/api/RLiveObject.java b/redisson/src/main/java/org/redisson/api/RLiveObject.java index f5e5576bb..4bcd9621f 100644 --- a/redisson/src/main/java/org/redisson/api/RLiveObject.java +++ b/redisson/src/main/java/org/redisson/api/RLiveObject.java @@ -38,4 +38,6 @@ public interface RLiveObject extends RExpirable { */ void setLiveObjectId(Object liveObjectId); + RMap getLiveObjectLiveMap(); + } diff --git a/redisson/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java b/redisson/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java index 7ddb1417e..1a1303083 100644 --- a/redisson/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java +++ b/redisson/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java @@ -31,6 +31,7 @@ import org.redisson.command.CommandAsyncExecutor; import org.redisson.command.CommandBatchService; import org.redisson.liveobject.misc.ClassUtils; import org.redisson.liveobject.misc.Introspectior; +import org.redisson.liveobject.resolver.MapResolver; import org.redisson.liveobject.resolver.NamingScheme; import java.lang.reflect.Field; @@ -56,9 +57,14 @@ public class AccessorInterceptor { private static final Pattern FIELD_PATTERN = Pattern.compile("^(get|set|is)"); private final CommandAsyncExecutor commandExecutor; + private final Class entityClass; + private final MapResolver mapResolver; - public AccessorInterceptor(CommandAsyncExecutor commandExecutor) { + public AccessorInterceptor(Class entityClass, CommandAsyncExecutor commandExecutor, + MapResolver mapResolver) { + this.entityClass = entityClass; this.commandExecutor = commandExecutor; + this.mapResolver = mapResolver; } @RuntimeType @@ -67,7 +73,9 @@ public class AccessorInterceptor { @SuperCall Callable superMethod, @AllArguments Object[] args, @This Object me, - @FieldValue("liveObjectLiveMap") RMap liveMap) throws Exception { + @FieldProxy("liveObjectLiveMap") LiveObjectInterceptor.Setter mapSetter, + @FieldProxy("liveObjectLiveMap") LiveObjectInterceptor.Getter mapGetter + ) throws Exception { if (isGetter(method, getREntityIdFieldName(me))) { return ((RLiveObject) me).getLiveObjectId(); } @@ -76,10 +84,13 @@ public class AccessorInterceptor { return null; } + Object id = ((RLiveObject) me).getLiveObjectId(); + RMap liveMap = mapResolver.resolve(commandExecutor, entityClass, id, mapSetter, mapGetter); + String fieldName = getFieldName(me.getClass().getSuperclass(), method); Field field = ClassUtils.getDeclaredField(me.getClass().getSuperclass(), fieldName); Class fieldType = field.getType(); - + if (isGetter(method, fieldName)) { if (Modifier.isTransient(field.getModifiers())) { return field.get(me); @@ -93,7 +104,7 @@ public class AccessorInterceptor { return ar; } } - + if (result != null && fieldType.isEnum()) { if (result instanceof String) { return Enum.valueOf((Class) fieldType, (String) result); @@ -114,7 +125,7 @@ public class AccessorInterceptor { if (arg != null && ClassUtils.isAnnotationPresent(arg.getClass(), REntity.class)) { throw new IllegalStateException("REntity object should be attached to Redisson first"); } - + if (arg instanceof RLiveObject) { RLiveObject liveObject = (RLiveObject) arg; @@ -129,11 +140,11 @@ public class AccessorInterceptor { return me; } - + if (!(arg instanceof RObject) && (arg instanceof Collection || arg instanceof Map) && TransformationMode.ANNOTATION_BASED - .equals(ClassUtils.getAnnotation(me.getClass().getSuperclass(), + .equals(ClassUtils.getAnnotation(me.getClass().getSuperclass(), REntity.class).fieldTransformation())) { RObject rObject = commandExecutor.getObjectBuilder().createObject(((RLiveObject) me).getLiveObjectId(), me.getClass().getSuperclass(), arg.getClass(), fieldName); if (arg != null) { @@ -151,7 +162,7 @@ public class AccessorInterceptor { arg = rObject; } } - + if (arg instanceof RObject) { if (commandExecutor instanceof CommandBatchService) { commandExecutor.getObjectBuilder().storeAsync((RObject) arg, fieldName, liveMap); @@ -185,7 +196,7 @@ public class AccessorInterceptor { } private static final Set> PRIMITIVE_CLASSES = new HashSet<>(Arrays.asList( - byte.class, short.class, int.class, long.class, float.class, double.class)); + byte.class, short.class, int.class, long.class, float.class, double.class)); private void removeIndex(RMap liveMap, Object me, Field field) { if (field.getAnnotation(RIndex.class) == null) { diff --git a/redisson/src/main/java/org/redisson/liveobject/core/LiveObjectInterceptor.java b/redisson/src/main/java/org/redisson/liveobject/core/LiveObjectInterceptor.java index e4045164c..c043b87a3 100644 --- a/redisson/src/main/java/org/redisson/liveobject/core/LiveObjectInterceptor.java +++ b/redisson/src/main/java/org/redisson/liveobject/core/LiveObjectInterceptor.java @@ -17,7 +17,6 @@ package org.redisson.liveobject.core; import net.bytebuddy.implementation.bind.annotation.*; import org.redisson.RedissonLiveObjectService; -import org.redisson.RedissonMap; import org.redisson.RedissonObject; import org.redisson.api.RFuture; import org.redisson.api.RLiveObject; @@ -25,7 +24,7 @@ import org.redisson.api.RMap; import org.redisson.client.RedisException; import org.redisson.command.CommandAsyncExecutor; import org.redisson.command.CommandBatchService; -import org.redisson.liveobject.misc.ClassUtils; +import org.redisson.liveobject.resolver.MapResolver; import org.redisson.liveobject.resolver.NamingScheme; import java.lang.reflect.InvocationTargetException; @@ -49,25 +48,18 @@ public class LiveObjectInterceptor { } private final CommandAsyncExecutor commandExecutor; - private final Class originalClass; - private final String idFieldName; - private final Class idFieldType; + private final Class entityClass; private final NamingScheme namingScheme; private final RedissonLiveObjectService service; + private final MapResolver mapResolver; - public LiveObjectInterceptor(CommandAsyncExecutor commandExecutor, RedissonLiveObjectService service, Class entityClass, String idFieldName) { + public LiveObjectInterceptor(CommandAsyncExecutor commandExecutor, RedissonLiveObjectService service, Class entityClass, + MapResolver mapResolver) { this.service = service; + this.mapResolver = mapResolver; this.commandExecutor = commandExecutor; - this.originalClass = entityClass; - this.idFieldName = idFieldName; - - namingScheme = commandExecutor.getObjectBuilder().getNamingScheme(entityClass); - - try { - this.idFieldType = ClassUtils.getDeclaredField(originalClass, idFieldName).getType(); - } catch (Exception e) { - throw new IllegalArgumentException(e); - } + this.entityClass = entityClass; + this.namingScheme = commandExecutor.getObjectBuilder().getNamingScheme(entityClass); } @RuntimeType @@ -86,34 +78,33 @@ public class LiveObjectInterceptor { if (args[0].getClass().isArray()) { throw new UnsupportedOperationException("RId value cannot be an array."); } - //TODO: distributed locking maybe required. - String idKey = getMapKey(args[0]); - if (map != null) { - if (((RedissonObject) map).getRawName().equals(idKey)) { - return null; - } - try { - map.rename(getMapKey(args[0])); - } catch (RedisException e) { - if (e.getMessage() == null || !e.getMessage().startsWith("ERR no such key")) { - throw e; + if (idGetter.getValue() != null) { + mapResolver.remove(entityClass, idGetter.getValue()); + + String idKey = namingScheme.getName(entityClass, args[0]); + if (map != null) { + if (((RedissonObject) map).getRawName().equals(idKey)) { + return map; + } + try { + map.rename(idKey); + idSetter.setValue(args[0]); + return null; + } catch (RedisException e) { + if (e.getMessage() == null || !e.getMessage().startsWith("ERR no such key")) { + throw e; + } + //key may already renamed by others. } - //key may already renamed by others. } } - RMap liveMap = new RedissonMap(namingScheme.getCodec(), commandExecutor, - idKey, null, null, null); - mapSetter.setValue(liveMap); - + idSetter.setValue(args[0]); return null; } if ("getLiveObjectId".equals(method.getName())) { - if (map == null) { - return null; - } - return namingScheme.resolveId(((RedissonObject) map).getRawName()); + return id; } if ("delete".equals(method.getName())) { @@ -127,10 +118,18 @@ public class LiveObjectInterceptor { Object idd = ((RLiveObject) me).getLiveObjectId(); RFuture deleteFuture = service.delete(idd, me.getClass().getSuperclass(), namingScheme, ce); ce.execute(); - + return commandExecutor.get(deleteFuture.toCompletableFuture()) > 0; } + if (map == null) { + map = mapResolver.resolve(commandExecutor, entityClass, id, mapSetter, mapGetter); + } + + if ("getLiveObjectLiveMap".equals(method.getName())) { + return map; + } + try { return method.invoke(map, args); } catch (InvocationTargetException e) { @@ -138,9 +137,4 @@ public class LiveObjectInterceptor { } } - - private String getMapKey(Object id) { - return namingScheme.getName(originalClass, id); - } - } diff --git a/redisson/src/main/java/org/redisson/liveobject/core/RExpirableInterceptor.java b/redisson/src/main/java/org/redisson/liveobject/core/RExpirableInterceptor.java deleted file mode 100644 index 6fc70cb0c..000000000 --- a/redisson/src/main/java/org/redisson/liveobject/core/RExpirableInterceptor.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2013-2024 Nikita Koksharov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.redisson.liveobject.core; - -import java.lang.reflect.Method; -import net.bytebuddy.implementation.bind.annotation.AllArguments; -import net.bytebuddy.implementation.bind.annotation.FieldValue; -import net.bytebuddy.implementation.bind.annotation.Origin; -import net.bytebuddy.implementation.bind.annotation.RuntimeType; -import org.redisson.api.RExpirable; -import org.redisson.api.RMap; -import org.redisson.liveobject.misc.ClassUtils; - -/** - * - * @author Rui Gu (https://github.com/jackygurui) - */ -public class RExpirableInterceptor { - - @RuntimeType - public static Object intercept( - @Origin Method method, - @AllArguments Object[] args, - @FieldValue("liveObjectLiveMap") RMap map - ) throws Exception { - Class[] cls = new Class[args.length]; - for (int i = 0; i < args.length; i++) { - cls[i] = args[i].getClass(); - } - return ClassUtils.searchForMethod(RExpirable.class, method.getName(), cls).invoke(map, args); - } -} diff --git a/redisson/src/main/java/org/redisson/liveobject/core/RMapInterceptor.java b/redisson/src/main/java/org/redisson/liveobject/core/RMapInterceptor.java index cddc277b9..7c90164c8 100644 --- a/redisson/src/main/java/org/redisson/liveobject/core/RMapInterceptor.java +++ b/redisson/src/main/java/org/redisson/liveobject/core/RMapInterceptor.java @@ -15,29 +15,41 @@ */ package org.redisson.liveobject.core; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - +import net.bytebuddy.implementation.bind.annotation.*; import org.redisson.api.RMap; +import org.redisson.command.CommandAsyncExecutor; +import org.redisson.liveobject.resolver.MapResolver; -import net.bytebuddy.implementation.bind.annotation.AllArguments; -import net.bytebuddy.implementation.bind.annotation.FieldValue; -import net.bytebuddy.implementation.bind.annotation.Origin; -import net.bytebuddy.implementation.bind.annotation.RuntimeType; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; /** * * @author Rui Gu (https://github.com/jackygurui) + * @author Nikita Koksharov */ public class RMapInterceptor { + private final CommandAsyncExecutor commandAsyncExecutor; + private final MapResolver mapResolver; + private final Class entityClass; + + public RMapInterceptor(CommandAsyncExecutor commandAsyncExecutor, Class entityClass, MapResolver mapResolver) { + this.commandAsyncExecutor = commandAsyncExecutor; + this.mapResolver = mapResolver; + this.entityClass = entityClass; + } + @RuntimeType - public static Object intercept( + public Object intercept( @Origin Method method, @AllArguments Object[] args, - @FieldValue("liveObjectLiveMap") RMap map + @FieldValue("liveObjectId") Object id, + @FieldProxy("liveObjectLiveMap") LiveObjectInterceptor.Setter mapSetter, + @FieldProxy("liveObjectLiveMap") LiveObjectInterceptor.Getter mapGetter ) throws Throwable { try { + RMap map = mapResolver.resolve(commandAsyncExecutor, entityClass, id, mapSetter, mapGetter); return method.invoke(map, args); } catch (InvocationTargetException e) { throw e.getCause(); diff --git a/redisson/src/main/java/org/redisson/liveobject/core/RObjectInterceptor.java b/redisson/src/main/java/org/redisson/liveobject/core/RObjectInterceptor.java deleted file mode 100644 index 400427f26..000000000 --- a/redisson/src/main/java/org/redisson/liveobject/core/RObjectInterceptor.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2013-2024 Nikita Koksharov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.redisson.liveobject.core; - -import java.lang.reflect.Method; -import net.bytebuddy.implementation.bind.annotation.AllArguments; -import net.bytebuddy.implementation.bind.annotation.FieldValue; -import net.bytebuddy.implementation.bind.annotation.Origin; -import net.bytebuddy.implementation.bind.annotation.RuntimeType; -import org.redisson.api.RMap; - -/** - * - * @author Rui Gu (https://github.com/jackygurui) - */ -public class RObjectInterceptor { - - @RuntimeType - public static Object intercept( - @Origin Method method, - @AllArguments Object[] args, - @FieldValue("liveObjectLiveMap") RMap map - ) throws Exception { - throw new UnsupportedOperationException("Please use RLiveObjectService instance for this type of functions"); - } -} diff --git a/redisson/src/main/java/org/redisson/liveobject/resolver/MapResolver.java b/redisson/src/main/java/org/redisson/liveobject/resolver/MapResolver.java new file mode 100644 index 000000000..0d848028a --- /dev/null +++ b/redisson/src/main/java/org/redisson/liveobject/resolver/MapResolver.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2013-2024 Nikita Koksharov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.redisson.liveobject.resolver; + +import org.redisson.RedissonMap; +import org.redisson.api.RMap; +import org.redisson.command.CommandAsyncExecutor; +import org.redisson.liveobject.core.LiveObjectInterceptor; + +/** + * + * @author Nikita Koksharov + * + */ +public final class MapResolver { + + public MapResolver() { + } + + public void remove(Class entityClass) { + } + + public void remove(Class entityClass, Object id) { + } + + public void destroy(Class entityClass, Object id) { + } + + public RMap resolve(CommandAsyncExecutor commandExecutor, Class entityClass, Object id, + LiveObjectInterceptor.Setter mapSetter, LiveObjectInterceptor.Getter mapGetter) { + if (mapGetter.getValue() != null) { + return (RMap) mapGetter.getValue(); + } + + NamingScheme namingScheme = commandExecutor.getObjectBuilder().getNamingScheme(entityClass); + String idKey = namingScheme.getName(entityClass, id); + + RMap lm = new RedissonMap<>(namingScheme.getCodec(), commandExecutor, + idKey, null, null, null); + + mapSetter.setValue(lm); + return lm; + } + +}