refactoring

pull/6244/head
Nikita Koksharov 4 months ago
parent 0de2169f4d
commit 1a92a610f8

@ -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<?>, Class<?>> classCache;
private final CommandAsyncExecutor commandExecutor;
private final LiveObjectSearch seachEngine;
private final MapResolver mapResolver;
public RedissonLiveObjectService(ConcurrentMap<Class<?>, 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<String, Object> getMap(Object proxied) {
return ClassUtils.getField(proxied, "liveObjectLiveMap");
return asLiveObject(proxied).getLiveObjectLiveMap();
}
private <T> Object generateId(Class<T> 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<T> 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> T detach(T attachedObject) {
addExpireListener(commandExecutor);
@ -448,15 +459,15 @@ public class RedissonLiveObjectService implements RLiveObjectService {
T detached = instantiateDetachedObject((Class<T>) attachedObject.getClass().getSuperclass(), asLiveObject(attachedObject).getLiveObjectId());
new BeanCopy(attachedObject, detached).declared(true).copy();
alreadyDetached.put(getMap(attachedObject).getName(), detached);
for (Entry<String, Object> obj : getMap(attachedObject).entrySet()) {
if (!checkCascade(attachedObject, RCascadeType.DETACH, obj.getKey())) {
continue;
}
if (obj.getValue() instanceof RSortedSet) {
SortedSet<Object> redissonSet = (SortedSet<Object>) obj.getValue();
Set<Object> set = new TreeSet<Object>(redissonSet.comparator());
Set<Object> set = new TreeSet<Object>(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<Object> redissonDeque = (Collection<Object>) obj.getValue();
Deque<Object> deque = new LinkedList<Object>();
Deque<Object> deque = new LinkedList<Object>();
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<Object> redissonQueue = (Collection<Object>) obj.getValue();
Queue<Object> queue = new LinkedList<Object>();
Queue<Object> queue = new LinkedList<Object>();
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<Object> set = new HashSet<Object>();
Set<Object> set = new HashSet<Object>();
Collection<Object> redissonSet = (Collection<Object>) 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<Object> list = new ArrayList<Object>();
List<Object> list = new ArrayList<Object>();
Collection<Object> redissonList = (Collection<Object>) 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<Object, Object> map = new LinkedHashMap<Object, Object>();
Map<Object, Object> map = new LinkedHashMap<Object, Object>();
Map<Object, Object> redissonMap = (Map<Object, Object>) obj.getValue();
for (Entry<Object, Object> 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 <T> void delete(T attachedObject) {
addExpireListener(commandExecutor);
@ -578,12 +589,12 @@ public class RedissonLiveObjectService implements RLiveObjectService {
private <T> void delete(T attachedObject, Set<String> deleted) {
validateAttached(attachedObject);
for (Entry<String, Object> 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<String, Object> liveMap = new RedissonMap<>(namingScheme.getCodec(), commandExecutor,
mapName, null, null, null);
mapName, null, null, null);
Map<String, ?> 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<Object> 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<FieldDescription.InDefinedShape> 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<FieldDescription.InDefinedShape> 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 <T> Class<? extends T> createProxy(Class<T> entityClass, CommandAsyncExecutor commandExecutor) {
DynamicType.Builder<T> builder = new ByteBuddy()
.subclass(entityClass);
@ -891,37 +905,32 @@ public class RedissonLiveObjectService implements RLiveObjectService {
}
Class<? extends T> 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();

@ -38,4 +38,6 @@ public interface RLiveObject extends RExpirable {
*/
void setLiveObjectId(Object liveObjectId);
RMap getLiveObjectLiveMap();
}

@ -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<String, Object> 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<String, Object> 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<Class<?>> 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<String, Object> liveMap, Object me, Field field) {
if (field.getAnnotation(RIndex.class) == null) {

@ -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<Object, Object> liveMap = new RedissonMap<Object, Object>(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<Long> 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);
}
}

@ -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);
}
}

@ -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();

@ -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");
}
}

@ -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<Object, Object> lm = new RedissonMap<>(namingScheme.getCodec(), commandExecutor,
idKey, null, null, null);
mapSetter.setValue(lm);
return lm;
}
}
Loading…
Cancel
Save