pull/527/head
jackygurui 9 years ago
parent 9cbbe48ab5
commit b24a3e9223

@ -1,18 +1,18 @@
package org.redisson;
import java.lang.reflect.Field;
import java.util.Map;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.ByteCodeElement;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import org.redisson.core.RExpirable;
import org.redisson.core.RExpirableAsync;
import org.redisson.core.RObject;
import org.redisson.core.RObjectAsync;
import org.redisson.liveobject.CodecProvider;
import org.redisson.liveobject.LiveObjectTemplate;
import org.redisson.liveobject.RAttachedLiveObjectService;
@ -20,6 +20,7 @@ import org.redisson.liveobject.RLiveObject;
import org.redisson.liveobject.annotation.REntity;
import org.redisson.liveobject.annotation.RId;
import org.redisson.liveobject.core.AccessorInterceptor;
import org.redisson.liveobject.core.ExpirableInterceptor;
import org.redisson.liveobject.misc.Introspectior;
public class RedissonAttachedLiveObjectService implements RAttachedLiveObjectService {
@ -95,8 +96,18 @@ public class RedissonAttachedLiveObjectService implements RAttachedLiveObjectSer
.and(ElementMatchers.isGetter().or(ElementMatchers.isSetter())))
.intercept(FieldAccessor.ofBeanProperty())
.implement(RLiveObject.class)
.method(ElementMatchers.isDeclaredBy(RExpirable.class)
.or(ElementMatchers.isDeclaredBy(RExpirableAsync.class))
.or(ElementMatchers.isDeclaredBy(RObject.class))
.or(ElementMatchers.isDeclaredBy(RObjectAsync.class)))
.intercept(MethodDelegation.to(new ExpirableInterceptor()))
.implement(RExpirable.class)
.method(ElementMatchers.not(ElementMatchers.isDeclaredBy(Object.class))
.and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RLiveObject.class)))
.and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RExpirable.class)))
.and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RExpirableAsync.class)))
.and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RObject.class)))
.and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RObjectAsync.class)))
.and(ElementMatchers.isGetter()
.or(ElementMatchers.isSetter()))
.and(ElementMatchers.isPublic()))

@ -8,42 +8,7 @@ import org.redisson.core.RMap;
*/
public class LiveObjectTemplate implements RLiveObject {
private Long liveObjectTTL;
private Object liveObjectId;
private RMap liveObjectLiveMap;
private String liveObjectMapKey;
/**
* @return the liveObjectTTL
*/
@Override
public Long getLiveObjectTTL() {
return liveObjectTTL;
}
/**
* @param liveObjectTTL the liveObjectTTL to set
*/
@Override
public void setLiveObjectTTL(Long liveObjectTTL) {
this.liveObjectTTL = liveObjectTTL;
}
/**
* @return the liveObjectId
*/
@Override
public Object getLiveObjectId() {
return liveObjectId;
}
/**
* @param liveObjectId the liveObjectId to set
*/
@Override
public void setLiveObjectId(Object liveObjectId) {
this.liveObjectId = liveObjectId;
}
/**
* @return the liveObjectLiveMap
@ -53,29 +18,4 @@ public class LiveObjectTemplate implements RLiveObject {
return liveObjectLiveMap;
}
/**
* @param liveObjectLiveMap the liveObjectLiveMap to set
*/
@Override
public void setLiveObjectLiveMap(RMap liveObjectLiveMap) {
this.liveObjectLiveMap = liveObjectLiveMap;
}
/**
* @return the liveObjectMapKey
*/
@Override
public String getLiveObjectMapKey() {
return liveObjectMapKey;
}
/**
* @param liveObjectMapKey the liveObjectMapKey to set
*/
@Override
public void setLiveObjectMapKey(String liveObjectMapKey) {
this.liveObjectMapKey = liveObjectMapKey;
}
}

@ -8,43 +8,8 @@ import org.redisson.core.RMap;
*/
public interface RLiveObject {
/**
* @return the liveObjectTTL
*/
public Long getLiveObjectTTL();
/**
* @param liveObjectTTL the liveObjectTTL to set
*/
public void setLiveObjectTTL(Long liveObjectTTL);
/**
* @return the LiveObjectId
*/
public Object getLiveObjectId();
/**
* @param LiveObjectId the LiveObjectId to set
*/
public void setLiveObjectId(Object LiveObjectId);
/**
* @return the liveObjectLiveMap
*/
public RMap getLiveObjectLiveMap();
/**
* @param liveObjectLiveMap the liveObjectLiveMap to set
*/
public void setLiveObjectLiveMap(RMap liveObjectLiveMap);
/**
* @return the liveObjectMapKey
*/
public String getLiveObjectMapKey();
/**
* @param liveObjectMapKey the liveObjectMapKey to set
*/
public void setLiveObjectMapKey(String liveObjectMapKey);
}

@ -1,5 +1,6 @@
package org.redisson.liveobject.core;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
@ -20,8 +21,9 @@ import org.redisson.liveobject.annotation.RId;
import org.redisson.liveobject.misc.Introspectior;
/**
* This class is going to be instantiated and becomes a <b>static</b> field of the proxied
* target class. That is one instance of this class per proxied class.
* This class is going to be instantiated and becomes a <b>static</b> field of
* the proxied target class. That is one instance of this class per proxied
* class.
*
* @author Rui Gu (https://github.com/jackygurui)
*/
@ -47,11 +49,10 @@ public class AccessorInterceptor {
@RuntimeType
public Object intercept(@Origin Method method, @SuperCall Callable<?> superMethod,
@AllArguments Object[] args, @This Object me) throws Exception {
RMap liveMap = getLiveMap(me);
if (isGetter(method, idFieldName)) {
return superMethod.call();
}
String id = getMapKey(getId(me));
RMap liveMap = redisson.getMap(id, codecProvider.getCodec(codecClass, RedissonMap.class, id));
if (isSetter(method, idFieldName)) {
//TODO: distributed locking maybe required.
try {
@ -89,6 +90,16 @@ public class AccessorInterceptor {
return superMethod.call();
}
private RMap getLiveMap(Object me) throws Exception {
RMap liveMap = (RMap) me.getClass().getField("liveObjectLiveMap").get(me);
if (liveMap == null) {
String id = getMapKey(getId(me));
liveMap = redisson.getMap(id, codecProvider.getCodec(codecClass, RedissonMap.class, id));
me.getClass().getField("liveObjectLiveMap").set(me, liveMap);
}
return liveMap;
}
private String getFieldName(Method method) {
return method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
}

@ -0,0 +1,137 @@
package org.redisson.liveobject.core;
import io.netty.util.concurrent.Future;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.This;
import org.redisson.client.codec.Codec;
import org.redisson.liveobject.RLiveObject;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class ExpirableInterceptor {
@RuntimeType
public boolean expire(@This Object me, long timeToLive, TimeUnit timeUnit) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public boolean expireAt(@This Object me, long timestamp) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public boolean expireAt(@This Object me, Date timestamp) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public boolean clearExpire(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public long remainTimeToLive(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public void migrate(@This Object me, String host, int port, int database) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public boolean move(@This Object me, int database) {
((RLiveObject) me).getLiveObjectLiveMap().move(database);
return true;
}
@RuntimeType
public String getName(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public boolean delete(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public void rename(@This Object me, String newName) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public boolean renamenx(@This Object me, String newName) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public boolean isExists(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Codec getCodec(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Void> migrateAsync(@This Object me, String host, int port, int database) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Boolean> moveAsync(@This Object me, int database) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Boolean> deleteAsync(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Void> renameAsync(@This Object me, String newName) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Boolean> renamenxAsync(@This Object me, String newName) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Boolean> isExistsAsync(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Boolean> expireAsync(@This Object me, long timeToLive, TimeUnit timeUnit) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Boolean> expireAtAsync(@This Object me, Date timestamp) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Boolean> expireAtAsync(@This Object me, long timestamp) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Boolean> clearExpireAsync(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@RuntimeType
public Future<Long> remainTimeToLiveAsync(@This Object me) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
Loading…
Cancel
Save