├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml ├── uiDesigner.xml └── vcs.xml ├── README.md ├── build.gradle ├── easy-reflect ├── build.gradle └── src │ ├── main │ └── java │ │ └── moe │ │ └── haruue │ │ └── reflect │ │ ├── EasyReflect.java │ │ ├── Getter.java │ │ ├── InjectMethod.java │ │ ├── ReflectHandler.java │ │ ├── ReflectionHelper.java │ │ └── Setter.java │ └── test │ └── java │ └── moe │ └── haruue │ └── reflect │ └── test │ ├── Base.java │ ├── Target.java │ └── Test.java ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | 24 | # IntelliJ IDEA 25 | *.iml 26 | .gradle 27 | /local.properties 28 | /.idea/workspace.xml 29 | /.idea/libraries 30 | .DS_Store 31 | /build 32 | /easy-reflect/build 33 | /captures 34 | .externalNativeBuild 35 | *.apk 36 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EasyReflect 2 | ----------- 3 | 4 | ## Overview 5 | 上 Java 课的时候无聊想出来的玩意儿,如果把 Java 反射机制的几门神器放在一起用会怎么样呢。。。 6 | 7 | 于是乎就有了这个! 8 | 9 | ## Download 10 | ``` Groovy 11 | dependencies { 12 | compile 'moe.haruue:easy-reflect:1.1.0' 13 | } 14 | ``` 15 | 16 | ## Usage 17 | 首先根据你要反射的类写一个接口,接口里包含有你要反射的方法的方法签名,此外你还可以使用 `@Setter` 和 `@Getter` 注解来创建一个字段的 Getter 和 Setter 方法。假如你要反射 `Target` 类的 `method` 方法和 `staticMethod` 方法,还需要反射 `field` 字段,那就这样写: 18 | 19 | ``` Java 20 | public interface TargetInterface { 21 | String method(int length); 22 | String staticMethod(int length); 23 | 24 | @Getter(name = "field") 25 | String getField(); 26 | 27 | @Setter(name = "field") 28 | void setField(String s); 29 | } 30 | ``` 31 | 32 | 然后使用 `EasyReflect` 创建代理,通过代理对象直接调用即可。。。 33 | 34 | ``` Java 35 | TargetInterface proxy = EasyReflect.from(target, TargetInterface.class); 36 | proxy.method(5); 37 | proxy.staticMethod(6); 38 | proxy.getField(); 39 | proxy.setField("abc"); 40 | ``` 41 | 42 | 如果你没有这个类的实例,甚至连这个类本身都需要在运行时反射出来,你仍然可以反射它的静态方法。。。 43 | 44 | ``` Java 45 | TargetInterface proxy = EasyReflect.from(null, Class.forName("moe.haruue.reflect.test.Target"), TargetInterface.class); 46 | proxy.staticMethod(7); 47 | ``` 48 | 49 | 静态字段的 Setter 和 Getter 等同于静态方法。 50 | 51 | ## Example 52 | 具体示例请戳 [这里](./easy-reflect/src/test/java/moe/haruue/reflect/test/Test.java) 53 | 54 | ## License 55 | 56 | ``` License 57 | Copyright 2017 Haruue Icymoon 58 | 59 | Licensed under the Apache License, Version 2.0 (the "License"); 60 | you may not use this file except in compliance with the License. 61 | You may obtain a copy of the License at 62 | 63 | http://www.apache.org/licenses/LICENSE-2.0 64 | 65 | Unless required by applicable law or agreed to in writing, software 66 | distributed under the License is distributed on an "AS IS" BASIS, 67 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 68 | See the License for the specific language governing permissions and 69 | limitations under the License. 70 | ``` 71 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | jcenter() 5 | } 6 | dependencies { 7 | classpath 'com.novoda:bintray-release:0.4.0' 8 | } 9 | } 10 | 11 | allprojects { 12 | repositories { 13 | jcenter() 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /easy-reflect/build.gradle: -------------------------------------------------------------------------------- 1 | group 'moe.haruue' 2 | version '1.1.0' 3 | 4 | apply plugin: 'java' 5 | apply plugin: 'com.novoda.bintray-release' 6 | 7 | sourceCompatibility = 1.5 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | testCompile group: 'junit', name: 'junit', version: '4.11' 15 | } 16 | 17 | publish { 18 | userOrg = 'haruue' 19 | groupId = 'moe.haruue' 20 | artifactId = 'easy-reflect' 21 | publishVersion = '1.1.0' 22 | desc = 'Tools make reflect easier' 23 | website = 'https://github.com/haruue/EasyReflect' 24 | } 25 | -------------------------------------------------------------------------------- /easy-reflect/src/main/java/moe/haruue/reflect/EasyReflect.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect; 2 | 3 | import java.lang.reflect.Proxy; 4 | 5 | /** 6 | * Exported interface of library 7 | * 8 | * @author Haruue Icymoon haruue@caoyue.com.cn 9 | */ 10 | public class EasyReflect { 11 | 12 | /** 13 | * Create reflect proxy for target as interfaceClazz, 14 | * if you don't have the instance of target, please use {@link #from(Object, Class, Class)} 15 | * 16 | * @param target target you want to reflect, can't be {@link null} 17 | * @param interfaceClazz a interface class for describe things you want to reflect 18 | * @param auto return type, will always be interfaceClass 19 | * @return a proxy object, you can call methods by it 20 | */ 21 | @SuppressWarnings("unchecked") 22 | public static T from(Object target, Class interfaceClazz) { 23 | return from(target, target.getClass(), interfaceClazz); 24 | } 25 | 26 | /** 27 | * Create reflect proxy for target as interfaceClazz, 28 | * it provide a way to call static method without the instance of the targetClass 29 | * you can use from(null, Target.class, TargetInterface.class) 30 | * 31 | * @param target target you want to reflect, can be {@link null} but instance methods will produce {@link NullPointerException} 32 | * @param targetClass the class of target 33 | * @param interfaceClazz a interface class for describe things you want to reflect 34 | * @param auto return type, will always be interfaceClass 35 | * @return a proxy object, you can call method by it 36 | */ 37 | @SuppressWarnings("unchecked") 38 | public static T from(Object target, Class targetClass, Class interfaceClazz) { 39 | return from(target, targetClass, ClassLoader.getSystemClassLoader(), interfaceClazz); 40 | } 41 | 42 | /** 43 | * Create reflect proxy for target as interfaceClazz, 44 | * it provide a way to use a customized class loader 45 | * 46 | * @param target target you want to reflect, can't be {@link null} 47 | * @param classLoader customized class loader 48 | * @param interfaceClazz a interface class for describe things you want to reflect 49 | * @param auto return type, will always be interfaceClass 50 | * @return a proxy object, you can call method by it 51 | */ 52 | @SuppressWarnings("unchecked") 53 | public static T from(Object target, ClassLoader classLoader, Class interfaceClazz) { 54 | return from(target, target.getClass(), classLoader, interfaceClazz); 55 | } 56 | 57 | /** 58 | * Create reflect proxy for target as interfaceClazz, 59 | * you can customize target and class loader 60 | * 61 | * @param target target you want to reflect, can be {@link null} but instance methods will produce {@link NullPointerException} 62 | * @param targetClass the class of target 63 | * @param classLoader customized class loader 64 | * @param interfaceClazz a interface class for describe things you want to reflect 65 | * @param auto return type, will always be interfaceClass 66 | * @return a proxy object, you can call method by it 67 | */ 68 | @SuppressWarnings("unchecked") 69 | public static T from(Object target, Class targetClass, ClassLoader classLoader, Class interfaceClazz) { 70 | return (T) Proxy.newProxyInstance(classLoader, 71 | new Class[]{interfaceClazz}, 72 | new ReflectHandler(target, targetClass)); 73 | } 74 | 75 | /** 76 | * Create reflect proxy for static members of target class as interfaceClazz, 77 | * you can customize target and class loader 78 | * 79 | * @param targetClass the class of target 80 | * @param classLoader customized class loader 81 | * @param interfaceClazz a interface class for describe things you want to reflect 82 | * @param auto return type, will always be interfaceClass 83 | * @return a proxy object, you can call method by it 84 | */ 85 | @SuppressWarnings("unchecked") 86 | public static T ofStatic(Class targetClass, ClassLoader classLoader, Class interfaceClazz) { 87 | return from(null, targetClass, classLoader, interfaceClazz); 88 | } 89 | 90 | /** 91 | * Create reflect proxy for static members of target as interfaceClazz, 92 | * 93 | * @param targetClass the class of target 94 | * @param interfaceClazz a interface class for describe things you want to reflect 95 | * @param auto return type, will always be interfaceClass 96 | * @return a proxy object, you can call method by it 97 | */ 98 | @SuppressWarnings("unchecked") 99 | public static T ofStatic(Class targetClass, Class interfaceClazz) { 100 | return from(null, targetClass, ClassLoader.getSystemClassLoader(), interfaceClazz); 101 | } 102 | 103 | 104 | } 105 | -------------------------------------------------------------------------------- /easy-reflect/src/main/java/moe/haruue/reflect/Getter.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Annotation to mark a method as a getter 11 | * 12 | * @author Haruue Icymoon haruue@caoyue.com.cn 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.METHOD) 16 | @Documented 17 | public @interface Getter { 18 | 19 | /** 20 | * The name of the field you want to reflect 21 | * 22 | * @return field name 23 | */ 24 | String name(); 25 | 26 | /** 27 | * Determine whether should search for the field in super class recursively. 28 | * 29 | * @return if returns false, proxy will search the field only in the target class. 30 | */ 31 | boolean searchSuper() default false; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /easy-reflect/src/main/java/moe/haruue/reflect/InjectMethod.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect; 2 | 3 | /** 4 | * Created by Stardust on 2017/6/22. 5 | */ 6 | 7 | import com.sun.istack.internal.NotNull; 8 | 9 | import java.lang.annotation.Documented; 10 | import java.lang.annotation.ElementType; 11 | import java.lang.annotation.Retention; 12 | import java.lang.annotation.RetentionPolicy; 13 | import java.lang.annotation.Target; 14 | 15 | /** 16 | * Annotation to mark a method to reflect 17 | * 18 | * @author Stardust hybbbb1996@gmail.com 19 | */ 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target(ElementType.METHOD) 22 | @Documented 23 | public @interface InjectMethod { 24 | 25 | /** 26 | * The name of method to reflect of target class. 27 | * For default, it will take the name of marked method to reflect. 28 | * 29 | * @return the method name 30 | */ 31 | String name() default ""; 32 | 33 | /** 34 | * Determine whether should search for the method in super class recursively. 35 | * 36 | * @return if returns false, proxy will search the method only in the target class. 37 | */ 38 | boolean searchSuper() default false; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /easy-reflect/src/main/java/moe/haruue/reflect/ReflectHandler.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.InvocationHandler; 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.lang.reflect.Method; 7 | import java.util.Locale; 8 | 9 | /** 10 | * Real handle which does reflect behind proxy 11 | * 12 | * @author Haruue Icymoon haruue@caoyue.com.cn 13 | */ 14 | class ReflectHandler implements InvocationHandler { 15 | 16 | Object target; 17 | Class targetClazz; 18 | 19 | ReflectHandler(Object target, Class targetClazz) { 20 | this.target = target; 21 | this.targetClazz = targetClazz; 22 | } 23 | 24 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 25 | Getter getter = method.getAnnotation(Getter.class); 26 | Setter setter = method.getAnnotation(Setter.class); 27 | if (getter != null && setter != null) { 28 | throw new IllegalArgumentException("method " + method.toGenericString() + " can not be @Getter and @Setter at the same time"); 29 | } 30 | if (getter != null) { 31 | return getValue(getter, method, args); 32 | } 33 | if (setter != null) { 34 | setValue(setter, method, args); 35 | return null; 36 | } 37 | return invokeMethod(method, args); 38 | } 39 | 40 | private Object getValue(Getter getter, Method method, Object[] args) throws NoSuchFieldException, IllegalAccessException { 41 | checkArgumentCount(method, args, 0); 42 | Field targetField = ReflectionHelper.getAccessibleField(targetClazz, getter.name(), getter.searchSuper()); 43 | return targetField.get(target); 44 | } 45 | 46 | private void setValue(Setter setter, Method method, Object[] args) throws NoSuchFieldException, IllegalAccessException { 47 | checkArgumentCount(method, args, 1); 48 | Field targetField = ReflectionHelper.getAccessibleField(targetClazz, setter.name(), setter.searchSuper()); 49 | targetField.set(target, args[0]); 50 | } 51 | 52 | private Object invokeMethod(Method method, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 53 | InjectMethod injectMethod = method.getAnnotation(InjectMethod.class); 54 | boolean searchSuper = injectMethod != null && injectMethod.searchSuper(); 55 | String methodName = method.getName(); 56 | if (injectMethod != null && injectMethod.name().length() > 0) { 57 | methodName = injectMethod.name(); 58 | } 59 | Method targetMethod = ReflectionHelper.getMethod(targetClazz, methodName, method.getParameterTypes(), searchSuper); 60 | targetMethod.setAccessible(true); 61 | return targetMethod.invoke(target, args); 62 | } 63 | 64 | private static void checkArgumentCount(Method method, Object[] args, int count) { 65 | if (count == 0) { 66 | if (args != null && args.length != count) { 67 | throw new IllegalArgumentException(String.format(Locale.getDefault(), "%s should have no argument", method.toGenericString())); 68 | } 69 | return; 70 | } 71 | if (args == null || args.length != count) { 72 | throw new IllegalArgumentException(String.format(Locale.getDefault(), "%s should have %d argument(s)", method.toGenericString(), count)); 73 | } 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /easy-reflect/src/main/java/moe/haruue/reflect/ReflectionHelper.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect; 2 | 3 | import com.sun.istack.internal.NotNull; 4 | 5 | import java.lang.reflect.Field; 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * Created by Stardust on 2017/6/22. 10 | */ 11 | 12 | final class ReflectionHelper { 13 | 14 | static Field getAccessibleField(Class objectClass, String fieldName, boolean searchSuperClass) throws NoSuchFieldException, SecurityException { 15 | Field field; 16 | try { 17 | field = objectClass.getDeclaredField(fieldName); 18 | } catch (NoSuchFieldException e) { 19 | if (!searchSuperClass || objectClass.getSuperclass() == null) { 20 | throw e; 21 | } else { 22 | field = getAccessibleField(objectClass.getSuperclass(), fieldName, true); 23 | } 24 | } 25 | field.setAccessible(true); 26 | return field; 27 | } 28 | 29 | 30 | static Method getMethod(Class objectClass, String methodName, Class[] paramTypes, boolean searchSuperClass) throws NoSuchMethodException, SecurityException { 31 | Method method; 32 | try { 33 | method = objectClass.getDeclaredMethod(methodName, paramTypes); 34 | } catch (NoSuchMethodException e) { 35 | if (!searchSuperClass || objectClass.getSuperclass() == null) { 36 | throw e; 37 | } else { 38 | method = getMethod(objectClass.getSuperclass(), methodName, paramTypes, true); 39 | } 40 | } 41 | return method; 42 | } 43 | 44 | private ReflectionHelper() { 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /easy-reflect/src/main/java/moe/haruue/reflect/Setter.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Annotation to mark a method as a setter 11 | * 12 | * @author Haruue Icymoon haruue@caoyue.com.cn 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.METHOD) 16 | @Documented 17 | public @interface Setter { 18 | 19 | /** 20 | * The name of the field you want to reflect 21 | * 22 | * @return field name 23 | */ 24 | String name(); 25 | 26 | /** 27 | * Determine whether should search for the field in super class recursively. 28 | * 29 | * @return if returns false, proxy will search the field only in the target class. 30 | */ 31 | boolean searchSuper() default false; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /easy-reflect/src/test/java/moe/haruue/reflect/test/Base.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect.test; 2 | 3 | /** 4 | * Created by Stardust on 2017/6/22. 5 | */ 6 | 7 | public class Base { 8 | 9 | private String superField = "this is super's instance field"; 10 | 11 | private static String superStaticField = "this is super's static field"; 12 | 13 | private String superMethod(int start) { 14 | return superField.substring(start); 15 | } 16 | 17 | private static String superStaticMethod(int start) { 18 | return superStaticField.substring(start); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /easy-reflect/src/test/java/moe/haruue/reflect/test/Target.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect.test; 2 | 3 | /** 4 | * Reflect target 5 | * @author Haruue Icymoon haruue@caoyue.com.cn 6 | */ 7 | public class Target extends Base { 8 | 9 | private String field = "this is a instance field"; 10 | 11 | private static String staticField = "this is a static field"; 12 | 13 | private String method(int length) { 14 | return field.substring(0, length); 15 | } 16 | 17 | private static String staticMethod(int length) { 18 | return staticField.substring(0, length); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /easy-reflect/src/test/java/moe/haruue/reflect/test/Test.java: -------------------------------------------------------------------------------- 1 | package moe.haruue.reflect.test; 2 | 3 | import moe.haruue.reflect.EasyReflect; 4 | import moe.haruue.reflect.Getter; 5 | import moe.haruue.reflect.InjectMethod; 6 | import moe.haruue.reflect.Setter; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | /** 11 | * @author Haruue Icymoon haruue@caoyue.com.cn 12 | */ 13 | public class Test { 14 | 15 | interface TargetInterface { 16 | String method(int length); 17 | 18 | String staticMethod(int length); 19 | 20 | @Getter(name = "field") 21 | String getField(); 22 | 23 | @Setter(name = "field") 24 | void setField(String s); 25 | 26 | @Getter(name = "staticField") 27 | String getStaticField(); 28 | 29 | @Setter(name = "staticField") 30 | void setStaticField(String s); 31 | 32 | @Getter(name = "noSuchField", searchSuper = true) 33 | void getInexistentField() throws NoSuchFieldException; 34 | 35 | @Getter(name = "superField", searchSuper = true) 36 | String getSuperField(); 37 | 38 | @Setter(name = "superField", searchSuper = true) 39 | void setSuperField(String s); 40 | 41 | @Getter(name = "superStaticField", searchSuper = true) 42 | String getSuperStaticField(); 43 | 44 | @Setter(name = "superStaticField", searchSuper = true) 45 | void setSuperStaticField(String s); 46 | 47 | @Getter(name = "superField") 48 | String getSuperFieldWithoutSearchingSuper() throws NoSuchFieldException; 49 | 50 | @InjectMethod(searchSuper = true) 51 | String superMethod(int start); 52 | 53 | @InjectMethod(searchSuper = true) 54 | String superStaticMethod(int start); 55 | 56 | } 57 | 58 | @org.junit.Test 59 | public void invokeWithInstance() throws Throwable { 60 | Target target = new Target(); 61 | TargetInterface proxy = EasyReflect.from(target, TargetInterface.class); 62 | assertEquals("this is a instance field", proxy.getField()); 63 | proxy.setField("reflected"); 64 | assertEquals("reflected", proxy.getField()); 65 | assertEquals("reflected".substring(0, 3), proxy.method(3)); 66 | } 67 | 68 | @org.junit.Test 69 | public void invokeWithoutInstance() throws Throwable { 70 | TargetInterface proxy = EasyReflect.from(null, Class.forName("moe.haruue.reflect.test.Target"), TargetInterface.class); 71 | assertEquals("this is a static field", proxy.getStaticField()); 72 | proxy.setStaticField("reflected"); 73 | assertEquals("reflected", proxy.getStaticField()); 74 | assertEquals("reflected".substring(0, 3), proxy.staticMethod(3)); 75 | } 76 | 77 | @org.junit.Test(expected = NoSuchFieldException.class) 78 | public void fieldOfTargetClassNotFound() throws Throwable { 79 | TargetInterface proxy = EasyReflect.from(new Target(), TargetInterface.class); 80 | proxy.getInexistentField(); 81 | } 82 | 83 | @org.junit.Test 84 | public void getFieldOfSuperClass() throws Throwable { 85 | TargetInterface proxy = EasyReflect.from(new Target(), TargetInterface.class); 86 | assertEquals("this is super's instance field", proxy.getSuperField()); 87 | } 88 | 89 | @org.junit.Test 90 | public void setFieldOfSuperClass() throws Throwable { 91 | TargetInterface proxy = EasyReflect.from(new Target(), TargetInterface.class); 92 | proxy.setSuperField("reflected"); 93 | assertEquals("reflected", proxy.getSuperField()); 94 | } 95 | 96 | @org.junit.Test 97 | public void getStaticFieldOfSuperClass() throws Throwable { 98 | TargetInterface proxy = EasyReflect.ofStatic(Target.class, TargetInterface.class); 99 | assertEquals("this is super's static field", proxy.getSuperStaticField()); 100 | } 101 | 102 | @org.junit.Test 103 | public void setStaticFieldOfSuperClass() throws Throwable { 104 | TargetInterface proxy = EasyReflect.ofStatic(Target.class, TargetInterface.class); 105 | String oldStaticField = proxy.getSuperStaticField(); 106 | proxy.setSuperStaticField("reflected"); 107 | assertEquals("reflected", proxy.getSuperStaticField()); 108 | proxy.setSuperStaticField(oldStaticField); 109 | assertEquals(oldStaticField, proxy.getSuperStaticField()); 110 | } 111 | 112 | @org.junit.Test(expected = NoSuchFieldException.class) 113 | public void getSuperFieldWithoutSearchingSuper() throws Throwable { 114 | TargetInterface proxy = EasyReflect.from(new Target(), TargetInterface.class); 115 | proxy.getSuperFieldWithoutSearchingSuper(); 116 | } 117 | 118 | 119 | @org.junit.Test 120 | public void invokeMethodOfSuperClass() throws Throwable { 121 | TargetInterface proxy = EasyReflect.from(new Target(), TargetInterface.class); 122 | assertEquals("is super's instance field", proxy.superMethod(5)); 123 | } 124 | 125 | 126 | @org.junit.Test 127 | public void invokeStaticMethodOfSuperClass() throws Throwable { 128 | TargetInterface proxy = EasyReflect.ofStatic(Target.class, TargetInterface.class); 129 | assertEquals("is super's static field", proxy.superStaticMethod(5)); 130 | } 131 | 132 | 133 | } 134 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Apr 06 16:20:47 CST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 165 | if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then 166 | cd "$(dirname "$0")" 167 | fi 168 | 169 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 170 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':easy-reflect' 2 | --------------------------------------------------------------------------------