Added FieldAccessor Support

Added FieldAccessorInterceptor
Added FieldAccessor annotation
Added test
pull/609/head
jackygurui 9 years ago
parent cbfb902d8f
commit e36ec9c9e4

@ -49,6 +49,8 @@ import org.redisson.api.RExpirableAsync;
import org.redisson.api.RMap;
import org.redisson.api.RMapAsync;
import org.redisson.api.RObjectAsync;
import org.redisson.api.annotation.RFieldAccessor;
import org.redisson.liveobject.core.FieldAccessorInterceptor;
import org.redisson.liveobject.core.RExpirableInterceptor;
import org.redisson.liveobject.core.RMapInterceptor;
import org.redisson.liveobject.core.RObjectInterceptor;
@ -328,6 +330,10 @@ public class RedissonLiveObjectService implements RLiveObjectService {
.install(LiveObjectInterceptor.Getter.class,
LiveObjectInterceptor.Setter.class)))
.implement(RLiveObject.class)
.method(ElementMatchers.isAnnotatedWith(RFieldAccessor.class)
.and(ElementMatchers.named("get")
.or(ElementMatchers.named("set"))))
.intercept(MethodDelegation.to(FieldAccessorInterceptor.class))
.method(ElementMatchers.isDeclaredBy(RObject.class)
.or(ElementMatchers.isDeclaredBy(RObjectAsync.class)))
.intercept(MethodDelegation.to(RObjectInterceptor.class))

@ -0,0 +1,29 @@
/**
* Copyright 2016 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.api.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface RFieldAccessor {}

@ -0,0 +1,61 @@
/**
* Copyright 2016 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.InvocationTargetException;
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 net.bytebuddy.implementation.bind.annotation.This;
import org.redisson.api.RMap;
import org.redisson.liveobject.misc.ClassUtils;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class FieldAccessorInterceptor {
@RuntimeType
public static Object intercept(
@Origin Method method,
@AllArguments Object[] args,
@This Object me,
@FieldValue("liveObjectLiveMap") RMap map
) throws Exception {
if (args.length >= 1 && String.class.isAssignableFrom(args[0].getClass())) {
String name = ((String) args[0]).substring(0, 1).toUpperCase() + ((String) args[0]).substring(1);
if ("get".equals(method.getName()) && args.length == 1) {
try {
return me.getClass().getMethod("get" + name).invoke(me);
} catch (NoSuchMethodException noSuchMethodException) {
throw new NoSuchFieldException((String) args[0]);
}
} else if ("set".equals(method.getName()) && args.length == 2) {
Method m = ClassUtils.searchForMethod(me.getClass(), "set" + name, new Class[]{args[1].getClass()});
if (m != null) {
return m.invoke(me, args[1]);
} else {
throw new NoSuchFieldException((String) args[0]);
}
}
}
throw new NoSuchMethodException(method.getName() + " called with wrong signature");
}
}

@ -40,6 +40,7 @@ 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;
import org.redisson.api.annotation.RId;
import org.redisson.liveobject.resolver.DefaultNamingScheme;
import org.redisson.liveobject.resolver.DistributedAtomicLongIdGenerator;
@ -391,6 +392,15 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
public void setContent(Object content) {
this.content = content;
}
@RFieldAccessor
public <T> void set(String field, T value) {
}
@RFieldAccessor
public <T> T get(String field) {
return null;
}
@Override
public boolean equals(Object obj) {
@ -965,5 +975,26 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
assertEquals("Please use RLiveObjectService instance for this type of functions", e.getMessage());
}
}
@Test
public void testFieldAccessor() {
RLiveObjectService service = redisson.getLiveObjectService();
TestClass myObject = service.create(TestClass.class);
myObject.setValue("123345");
assertEquals("123345", myObject.get("value"));
myObject.set("value", "9999");
assertEquals("9999", myObject.get("value"));
assertEquals("9999", myObject.getValue());
try {
myObject.get("555555");
} catch (Exception e) {
assertTrue(e instanceof NoSuchFieldException);
}
try {
myObject.set("555555", "999");
} catch (Exception e) {
assertTrue(e instanceof NoSuchFieldException);
}
}
}

Loading…
Cancel
Save