LiveObjectService doesn't support protected constructors #645

pull/653/head
Nikita 8 years ago
parent 87be1e3bc9
commit 000fb85375

@ -18,16 +18,23 @@ package org.redisson;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentMap;
import org.redisson.api.RDeque;
import org.redisson.api.RExpirable;
import org.redisson.api.RExpirableAsync;
import org.redisson.api.RList;
@ -37,6 +44,9 @@ import org.redisson.api.RMap;
import org.redisson.api.RMapAsync;
import org.redisson.api.RObject;
import org.redisson.api.RObjectAsync;
import org.redisson.api.RQueue;
import org.redisson.api.RSet;
import org.redisson.api.RSortedSet;
import org.redisson.api.RedissonClient;
import org.redisson.api.annotation.REntity;
import org.redisson.api.annotation.RFieldAccessor;
@ -58,8 +68,10 @@ import jodd.bean.BeanCopy;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.FieldProxy;
import net.bytebuddy.matcher.ElementMatchers;
@ -180,8 +192,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
}
T attachedObject = attach(detachedObject);
RLiveObject liveObject = asLiveObject(attachedObject);
if (getMap(liveObject).fastPut("redisson_live_object", "1")) {
if (getMap(attachedObject).fastPut("redisson_live_object", "1")) {
copy(detachedObject, attachedObject);
return attachedObject;
}
@ -199,29 +210,119 @@ public class RedissonLiveObjectService implements RLiveObjectService {
validateAttached(attachedObject);
try {
T detached = instantiateDetachedObject((Class<T>) attachedObject.getClass().getSuperclass(), asLiveObject(attachedObject).getLiveObjectId());
BeanCopy.beans(attachedObject, detached).declared(false, true).copy();
BeanCopy.beans(attachedObject, detached).declared(true, true).copy();
alreadyDetached.put(getMap(attachedObject).getName(), detached);
for (Entry<String, Object> obj : getMap(attachedObject).entrySet()) {
if (obj.getValue() instanceof RedissonList) {
List<Object> list = new ArrayList<Object>((List<Object>)obj.getValue());
for (int i = 0; i < list.size(); i++) {
Object object = list.get(i);
if (obj.getValue() instanceof RSortedSet) {
SortedSet<Object> redissonSet = (SortedSet<Object>) obj.getValue();
Set<Object> set = new TreeSet<Object>(redissonSet.comparator());
for (Object object : redissonSet) {
if (isLiveObject(object)) {
Object detachedObject = alreadyDetached.get(getMap(object).getName());
if (detachedObject == null) {
detachedObject = detach(object, alreadyDetached);
}
object = detachedObject;
}
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>();
for (Object object : redissonDeque) {
if (isLiveObject(object)) {
Object detachedObject = alreadyDetached.get(getMap(object).getName());
if (detachedObject == null) {
detachedObject = detach(object, alreadyDetached);
}
object = detachedObject;
}
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>();
for (Object object : redissonQueue) {
if (isLiveObject(object)) {
Object detachedObject = alreadyDetached.get(getMap(object).getName());
if (detachedObject == null) {
detachedObject = detach(object, alreadyDetached);
}
object = detachedObject;
}
queue.add(object);
}
ClassUtils.setField(detached, obj.getKey(), queue);
} else if (obj.getValue() instanceof RSet) {
Set<Object> set = new HashSet<Object>();
Collection<Object> redissonSet = (Collection<Object>) obj.getValue();
for (Object object : redissonSet) {
if (isLiveObject(object)) {
Object detachedObject = alreadyDetached.get(getMap(object).getName());
if (detachedObject == null) {
detachedObject = detach(object, alreadyDetached);
}
object = detachedObject;
}
set.add(object);
}
ClassUtils.setField(detached, obj.getKey(), set);
} else if (obj.getValue() instanceof RList) {
List<Object> list = new ArrayList<Object>();
Collection<Object> redissonList = (Collection<Object>) obj.getValue();
for (Object object : redissonList) {
if (isLiveObject(object)) {
Object detachedObject = alreadyDetached.get(getMap(object).getName());
if (detachedObject == null) {
detachedObject = detach(object, alreadyDetached);
}
list.set(i, detachedObject);
object = detachedObject;
}
list.add(object);
}
ClassUtils.setField(detached, obj.getKey(), list);
}
if (isLiveObject(obj.getValue())) {
Object detachedObject = alreadyDetached.get(getMap(obj.getValue()).getName());
if (detachedObject == null) {
detachedObject = detach(obj.getValue(), alreadyDetached);
}
ClassUtils.setField(detached, obj.getKey(), detachedObject);
} else if (obj.getValue() instanceof RMap) {
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) {
detachedObject = detach(key, alreadyDetached);
}
key = detachedObject;
}
if (isLiveObject(value)) {
Object detachedObject = alreadyDetached.get(getMap(value).getName());
if (detachedObject == null) {
detachedObject = detach(value, alreadyDetached);
}
value = detachedObject;
}
map.put(key, value);
}
ClassUtils.setField(detached, obj.getKey(), map);
}
}
@ -287,6 +388,86 @@ public class RedissonLiveObjectService implements RLiveObjectService {
}
private <T> void copy(T detachedObject, T attachedObject) {
// for (FieldDescription.InDefinedShape field : Introspectior.getFieldsDescription(detachedObject.getClass())) {
// Object obj = ClassUtils.getField(detachedObject, field.getName());
// if (obj instanceof SortedSet) {
// ClassUtils.getField(detachedObject, field.getName());
// SortedSet<Object> redissonSet = (SortedSet<Object>) obj.getValue();
// Set<Object> set = new TreeSet<Object>(redissonSet.comparator());
// for (Object object : redissonSet) {
// if (isLiveObject(object)) {
// Object detachedObject = alreadyDetached.get(getMap(object).getName());
// if (detachedObject == null) {
// detachedObject = detach(object, alreadyDetached);
// }
// object = detachedObject;
// }
// 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>();
// for (Object object : redissonDeque) {
// if (isLiveObject(object)) {
// Object detachedObject = alreadyDetached.get(getMap(object).getName());
// if (detachedObject == null) {
// detachedObject = detach(object, alreadyDetached);
// }
// object = detachedObject;
// }
// 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>();
// for (Object object : redissonQueue) {
// if (isLiveObject(object)) {
// Object detachedObject = alreadyDetached.get(getMap(object).getName());
// if (detachedObject == null) {
// detachedObject = detach(object, alreadyDetached);
// }
// object = detachedObject;
// }
// queue.add(object);
// }
//
// ClassUtils.setField(detached, obj.getKey(), queue);
// } else if (obj.getValue() instanceof RSet) {
// Set<Object> set = new HashSet<Object>();
// Collection<Object> redissonSet = (Collection<Object>) obj.getValue();
// for (Object object : redissonSet) {
// if (isLiveObject(object)) {
// Object detachedObject = alreadyDetached.get(getMap(object).getName());
// if (detachedObject == null) {
// detachedObject = detach(object, alreadyDetached);
// }
// object = detachedObject;
// }
// set.add(object);
// }
//
// ClassUtils.setField(detached, obj.getKey(), set);
// } else if (obj.getValue() instanceof RList) {
// List<Object> list = new ArrayList<Object>();
// Collection<Object> redissonList = (Collection<Object>) obj.getValue();
// for (Object object : redissonList) {
// if (isLiveObject(object)) {
// Object detachedObject = alreadyDetached.get(getMap(object).getName());
// if (detachedObject == null) {
// detachedObject = detach(object, alreadyDetached);
// }
// object = detachedObject;
// }
// list.add(object);
// }
//
// ClassUtils.setField(detached, obj.getKey(), list);
// }
// }
String idFieldName = getRIdFieldName(detachedObject.getClass());
BeanCopy.beans(detachedObject, attachedObject)
.ignoreNulls(true)
@ -319,16 +500,13 @@ public class RedissonLiveObjectService implements RLiveObjectService {
}
private <T, K> T instantiate(Class<T> cls, K id) throws Exception {
try {
return cls.newInstance();
} catch (Exception exception) {
for (Constructor<?> ctor : classCache.containsKey(cls) ? cls.getConstructors() : cls.getDeclaredConstructors()) {
if (ctor.getParameterTypes().length == 1 && ctor.getParameterTypes()[0].isAssignableFrom(id.getClass())) {
return (T) ctor.newInstance(id);
}
for (Constructor<?> constructor : cls.getDeclaredConstructors()) {
if (constructor.getParameterCount() == 0) {
constructor.setAccessible(true);
return (T) constructor.newInstance();
}
}
throw new NoSuchMethodException("Unable to find constructor matching only the RId field type [" + id.getClass().getCanonicalName() + "].");
throw new IllegalArgumentException("Can't find default constructor for " + cls);
}
private <T> Class<? extends T> getProxyClass(Class<T> entityClass) {

@ -60,6 +60,9 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
private String name;
private String value;
protected TestREntity() {
}
public TestREntity(String name) {
this.name = name;
}
@ -103,6 +106,9 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
private String name;
private RMap value;
protected TestREntityWithRMap() {
}
public TestREntityWithRMap(String name) {
this.name = name;
}
@ -234,6 +240,9 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
private String name;
private TestREntityWithRMap value;
protected TestREntityValueNested() {
}
public TestREntityValueNested(String name) {
this.name = name;
}
@ -1243,4 +1252,40 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
assertThat(o.getCustomer().getId()).isEqualTo(customer.getId());
}
@REntity
public static class ClassWithoutIdSetterGetter {
@RId(generator = DistributedAtomicLongIdGenerator.class)
private Long id;
private String name;
protected ClassWithoutIdSetterGetter() {
System.out.println("123");
}
public ClassWithoutIdSetterGetter(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
}
@Test
public void testWithoutIdSetterGetter() {
ClassWithoutIdSetterGetter sg = new ClassWithoutIdSetterGetter();
sg = redisson.getLiveObjectService().persist(sg);
}
@Test
public void testProtectedConstructor() {
ClassWithoutIdSetterGetter sg = new ClassWithoutIdSetterGetter("1234");
sg = redisson.getLiveObjectService().persist(sg);
assertThat(sg.getName()).isEqualTo("1234");
}
}

Loading…
Cancel
Save