diff --git a/redisson/src/main/java/org/redisson/misc/ProxyBuilder.java b/redisson/src/main/java/org/redisson/misc/ProxyBuilder.java new file mode 100644 index 000000000..d3c6570ee --- /dev/null +++ b/redisson/src/main/java/org/redisson/misc/ProxyBuilder.java @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2013-2019 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.misc; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * + * @author Nikita Koksharov + * + */ +//TODO refactor to common object and MethodHandles +//MethodHandle mh = MethodHandles.lookup().findVirtual(implementation.getClass(), method.getName(), +// MethodType.methodType(method.getReturnType(), method.getParameterTypes())); +public class ProxyBuilder { + + public interface Callback { + + Object execute(Method mm, Object instance, Object[] args); + + } + + private static class CacheKey { + + Method method; + Class instanceClass; + + public CacheKey(Method method, Class instanceClass) { + super(); + this.method = method; + this.instanceClass = instanceClass; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((instanceClass == null) ? 0 : instanceClass.hashCode()); + result = prime * result + ((method == null) ? 0 : method.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CacheKey other = (CacheKey) obj; + if (instanceClass == null) { + if (other.instanceClass != null) + return false; + } else if (!instanceClass.equals(other.instanceClass)) + return false; + if (method == null) { + if (other.method != null) + return false; + } else if (!method.equals(other.method)) + return false; + return true; + } + + } + + private static final ConcurrentMap methodsMapping = new ConcurrentHashMap(); + + public static T create(final Callback commandExecutor, final Object instance, final Object implementation, final Class clazz) { + InvocationHandler handler = new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, final Object[] args) throws Throwable { + CacheKey key = new CacheKey(method, instance.getClass()); + Method instanceMethod = methodsMapping.get(key); + if (instanceMethod == null) { + if (implementation != null) { + try { + instanceMethod = implementation.getClass().getMethod(method.getName(), method.getParameterTypes()); + } catch (NoSuchMethodException e) { + try { + instanceMethod = instance.getClass().getMethod(method.getName() + "Async", method.getParameterTypes()); + } catch (Exception e2) { + instanceMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes()); + } + } + } else { + try { + instanceMethod = instance.getClass().getMethod(method.getName() + "Async", method.getParameterTypes()); + } catch (NoSuchMethodException e) { + instanceMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes()); + } + } + + methodsMapping.put(key, instanceMethod); + } + final Method mm = instanceMethod; + if (instanceMethod.getName().endsWith("Async")) { + return commandExecutor.execute(mm, instance, args); + } + + if (implementation != null + && instanceMethod.getDeclaringClass().isAssignableFrom(implementation.getClass())) { + return instanceMethod.invoke(implementation, args); + } + + return instanceMethod.invoke(instance, args); + } + }; + return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, handler); + } + +} diff --git a/redisson/src/main/java/org/redisson/reactive/ReactiveProxyBuilder.java b/redisson/src/main/java/org/redisson/reactive/ReactiveProxyBuilder.java index 264b4bab1..0536419e7 100644 --- a/redisson/src/main/java/org/redisson/reactive/ReactiveProxyBuilder.java +++ b/redisson/src/main/java/org/redisson/reactive/ReactiveProxyBuilder.java @@ -15,13 +15,11 @@ */ package org.redisson.reactive; -import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import org.redisson.api.RFuture; +import org.redisson.misc.ProxyBuilder; +import org.redisson.misc.ProxyBuilder.Callback; import reactor.fn.Supplier; @@ -30,113 +28,28 @@ import reactor.fn.Supplier; * @author Nikita Koksharov * */ -//TODO refactor to common object and MethodHandles -//MethodHandle mh = MethodHandles.lookup().findVirtual(implementation.getClass(), method.getName(), -// MethodType.methodType(method.getReturnType(), method.getParameterTypes())); public class ReactiveProxyBuilder { - private static class CacheKey { - - Method method; - Class instanceClass; - - public CacheKey(Method method, Class instanceClass) { - super(); - this.method = method; - this.instanceClass = instanceClass; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((instanceClass == null) ? 0 : instanceClass.hashCode()); - result = prime * result + ((method == null) ? 0 : method.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - CacheKey other = (CacheKey) obj; - if (instanceClass == null) { - if (other.instanceClass != null) - return false; - } else if (!instanceClass.equals(other.instanceClass)) - return false; - if (method == null) { - if (other.method != null) - return false; - } else if (!method.equals(other.method)) - return false; - return true; - } - - } - - private static final ConcurrentMap methodsMapping = new ConcurrentHashMap(); - public static T create(CommandReactiveExecutor commandExecutor, Object instance, Class clazz) { return create(commandExecutor, instance, null, clazz); } - public static T create(final CommandReactiveExecutor commandExecutor, final Object instance, final Object implementation, final Class clazz) { - InvocationHandler handler = new InvocationHandler() { + public static T create(final CommandReactiveExecutor commandExecutor, Object instance, Object implementation, Class clazz) { + return ProxyBuilder.create(new Callback() { @Override - public Object invoke(Object proxy, Method method, final Object[] args) throws Throwable { - CacheKey key = new CacheKey(method, instance.getClass()); - Method instanceMethod = methodsMapping.get(key); - if (instanceMethod == null) { - if (implementation != null) { - try { - instanceMethod = implementation.getClass().getMethod(method.getName(), method.getParameterTypes()); - } catch (NoSuchMethodException e) { - try { - instanceMethod = instance.getClass().getMethod(method.getName() + "Async", method.getParameterTypes()); - } catch (Exception e2) { - instanceMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes()); - } - } - } else { + public Object execute(final Method mm, final Object instance, final Object[] args) { + return commandExecutor.reactive(new Supplier>() { + @Override + public RFuture get() { try { - instanceMethod = instance.getClass().getMethod(method.getName() + "Async", method.getParameterTypes()); - } catch (NoSuchMethodException e) { - instanceMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes()); + return (RFuture) mm.invoke(instance, args); + } catch (Exception e) { + throw new IllegalStateException(e); } } - - methodsMapping.put(key, instanceMethod); - } - - final Method mm = instanceMethod; - if (instanceMethod.getName().endsWith("Async")) { - return commandExecutor.reactive(new Supplier>() { - @SuppressWarnings("unchecked") - @Override - public RFuture get() { - try { - return (RFuture) mm.invoke(instance, args); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - }); - } - - if (implementation != null - && instanceMethod.getDeclaringClass() == implementation.getClass()) { - return instanceMethod.invoke(implementation, args); - } - - return instanceMethod.invoke(instance, args); + }); } - }; - return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, handler); + }, instance, implementation, clazz); } } diff --git a/redisson/src/main/java/org/redisson/rx/RxProxyBuilder.java b/redisson/src/main/java/org/redisson/rx/RxProxyBuilder.java index bf37d061e..c51386342 100644 --- a/redisson/src/main/java/org/redisson/rx/RxProxyBuilder.java +++ b/redisson/src/main/java/org/redisson/rx/RxProxyBuilder.java @@ -15,126 +15,41 @@ */ package org.redisson.rx; -import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; -import java.lang.reflect.Proxy; import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import org.redisson.api.RFuture; +import org.redisson.misc.ProxyBuilder; +import org.redisson.misc.ProxyBuilder.Callback; /** * * @author Nikita Koksharov * */ -//TODO refactor to common object and MethodHandles -//MethodHandle mh = MethodHandles.lookup().findVirtual(implementation.getClass(), method.getName(), -// MethodType.methodType(method.getReturnType(), method.getParameterTypes())); public class RxProxyBuilder { - private static class CacheKey { - - Method method; - Class instanceClass; - - public CacheKey(Method method, Class instanceClass) { - super(); - this.method = method; - this.instanceClass = instanceClass; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((instanceClass == null) ? 0 : instanceClass.hashCode()); - result = prime * result + ((method == null) ? 0 : method.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - CacheKey other = (CacheKey) obj; - if (instanceClass == null) { - if (other.instanceClass != null) - return false; - } else if (!instanceClass.equals(other.instanceClass)) - return false; - if (method == null) { - if (other.method != null) - return false; - } else if (!method.equals(other.method)) - return false; - return true; - } - - } - - private static final ConcurrentMap methodsMapping = new ConcurrentHashMap(); - public static T create(CommandRxExecutor commandExecutor, Object instance, Class clazz) { return create(commandExecutor, instance, null, clazz); } - public static T create(final CommandRxExecutor commandExecutor, final Object instance, final Object implementation, final Class clazz) { - InvocationHandler handler = new InvocationHandler() { + public static T create(final CommandRxExecutor commandExecutor, Object instance, Object implementation, Class clazz) { + return ProxyBuilder.create(new Callback() { @Override - public Object invoke(Object proxy, Method method, final Object[] args) throws Throwable { - CacheKey key = new CacheKey(method, instance.getClass()); - Method instanceMethod = methodsMapping.get(key); - if (instanceMethod == null) { - if (implementation != null) { - try { - instanceMethod = implementation.getClass().getMethod(method.getName(), method.getParameterTypes()); - } catch (NoSuchMethodException e) { - try { - instanceMethod = instance.getClass().getMethod(method.getName() + "Async", method.getParameterTypes()); - } catch (Exception e2) { - instanceMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes()); - } - } - } else { + public Object execute(final Method mm, final Object instance, final Object[] args) { + return commandExecutor.flowable(new Callable>() { + @SuppressWarnings("unchecked") + @Override + public RFuture call() { try { - instanceMethod = instance.getClass().getMethod(method.getName() + "Async", method.getParameterTypes()); - } catch (NoSuchMethodException e) { - instanceMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes()); + return (RFuture) mm.invoke(instance, args); + } catch (Exception e) { + throw new IllegalStateException(e); } } - - methodsMapping.put(key, instanceMethod); - } - final Method mm = instanceMethod; - if (instanceMethod.getName().endsWith("Async")) { - return commandExecutor.flowable(new Callable>() { - @SuppressWarnings("unchecked") - @Override - public RFuture call() { - try { - return (RFuture) mm.invoke(instance, args); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - }); - } - - if (implementation != null - && instanceMethod.getDeclaringClass().isAssignableFrom(implementation.getClass())) { - return instanceMethod.invoke(implementation, args); - } - - return instanceMethod.invoke(instance, args); + }); } - }; - return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, handler); + }, instance, implementation, clazz); } }