反射 反射就是把Java类中的各种成分映射成一个个的java对象。 例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个 对象。可能把它说成解剖更容易理解。 /** 关于Constructor类,其实例对象代表类的一个构造方法。 1、得到某个类所有的构造方法,例: Constructor [] constructors= Class.forName("java.lang.String").getConstructors(); 2、得到某一个构造方法,例: Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class); 3、利用构造方法创建实例对象: String str = (String)constructor.newInstance(“abc”); 4、Class类的newInstance()方法也可创建类的实例,其内部工作原理是先得无参的构造方法,再用构造方法创建实例对象。 String obj =(String)Class.forName("java.lang.String").newInstance(); */ //反射构造函数示例: //反射构造函数 public Person() @Test public void test1() throws Exception{ Class clazz = Class.forName("he.junhua.reflect.Person"); Constructor c = clazz.getConstructor(null); //public Person p = (Person) c.newInstance(null); System.out.println(p.name); } //另一种方法,等效于上。要求类中必须有无参构造函数 @Test public void test5() throws Exception{ Class clazz = Class.forName("he.junhua.reflect.Person"); Person p = (Person) clazz.newInstance(); System.out.println(p); } //反射构造函数 public Person(String name) @Test public void test2() throws Exception{ Class clazz = Class.forName("he.junhua.reflect.Person"); Constructor c = clazz.getConstructor(String .class); Person p = (Person) c.newInstance("xxx"); System.out.println(p.name); } //反射构造函数 private Person(List list) @Test public void test4() throws Exception{ Class clazz = Class.forName("he.junhua.reflect.Person"); Constructor c = clazz.getDeclaredConstructor(List .class); //包括private c.setAccessible(true); //暴力手段,强制开启访问权限 Person p = (Person) c.newInstance(new ArrayList()); System.out.println(p.name); } /** Field类代表某个类中的一个成员变量 问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量? 类只有一个,而该类的实例对象有多个,如果是与对象关联,哪关联的是哪个对象呢? 所以字段fieldX 代表的是x的定义,而不是具体的x变量。(注意访问权限的问题) 例: //Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getField("x"); Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getDeclaredField("x"); x.setAccessible(true); */ //反射字段示例: //反射字段 public String name = "aaa"; @Test public void test1() throws Exception{ Person p = new Person(); Class clazz = Class.forName("he.junhua.reflect.Person"); Field f = clazz.getField("name"); //获取字段的值 Object value = f.get(p); //获取字段的类型 Type type = f.getType(); //判断字段 if (type.equals(String .class)) { String svalue = (String) value; System.out.println(svalue); } //设置字段的值 f.set(p, "bbb"); System.out.println(p.name); } //反射字段 private int password = 123; @Test public void test2() throws Exception{ Person p = new Person(); Class clazz = Class.forName("he.junhua.reflect.Person"); Field f = clazz.getDeclaredField("password"); //private //暴力打开权限 f.setAccessible(true); //获取字段的值 Integer pwd = (Integer) f.get(p); System.out.println(pwd); } /** 关于Method类,其代表某个类中的一个成员方法 1、得到类中的某一个方法: 例子: Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class); 2、调用方法: ·通常方式:System.out.println(str.charAt(1)); ·反射方式: System.out.println(charAt.invoke(str, 1)); 注意:如果传递给Method对象的invoke()方法的第一个参数为null,说明该Method对象对应的必定是一个静态方法! 3、jdk1.4和jdk1.5的invoke方法的区别: Jdk1.5:public Object invoke(Object obj,Object... args) Jdk1.4:public Object invoke(Object obj,Object[] args), 即按jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数, 所以,调用charAt方法的代码也可以用Jdk1.4改写为 charAt.invoke(“str”, new Object[]{1})形式。 */ //反射方法示例: //反射方法 public void m() @Test public void test1() throws Exception{ Person p = new Person(); Class clazz = Class.forName("he.junhua.reflect.Person"); Method method = clazz.getMethod("m", null); method.invoke(p, null); } //反射方法 public Class[] m(String name,int[] password) @Test public void test3() throws Exception{ Person p = new Person(); Class clazz = Class.forName("he.junhua.reflect.Person"); Method method = clazz.getMethod("m", String .class,int[] .class); method.invoke(p, "ok",new int[]{1,2,3}); } //反射方法(私有) private void m(FileInputStream in) @Test public void test4() throws Exception{ Person p = new Person(); Class clazz = Class.forName("he.junhua.reflect.Person"); Method method = clazz.getDeclaredMethod("m", FileInputStream .class); method.setAccessible(true); method.invoke(p, new FileInputStream("D:a.txt")); } //反射方法(静态) public static void m(int num) @Test public void test5() throws Exception{ //Person p = new Person(); Class clazz = Class.forName("he.junhua.reflect.Person"); Method method = clazz.getDeclaredMethod("m", int .class); method.invoke(null, 1); //静态方法可以直接调用,故不需要再new出一个Person对象 } /** 最后要注意用反射方式执行某个类中的main方法 1、目标: 写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。用普通方式调完后,大家要明白为什么要用反射方式去调啊? 2、问题: 启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args), 通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢? 按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数, 当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢? jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。 所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}), javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。 3、解决办法: mainMethod.invoke(null,new Object[]{new String[]{"xxx"}}); mainMethod.invoke(null,(Object)new String[]{"xxx"}); //编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了 */ //反射main函数示例: //反射main函数 public static void main(String[] args) @Test public void test6() throws Exception{ //Person p = new Person(); Class clazz = Class.forName("he.junhua.reflect.Person"); Method method = clazz.getDeclaredMethod("main", String[] .class); method.invoke(null,(Object)new String[]{"aa","bb"}); //method.invoke(null,new Object[]{new String[]{"aa","bb"}}); }
Java基于反射实现自定义切面
转载文章标签 Java基于反射实现自定义切面 java中用到反射机制 Test System 字段 文章分类 Java 后端开发
-
java 切面 实现日志 自定义注解 java切面怎么写
5、面向切面:AOP5.1 场景模拟模拟+ - * / 运算5.1.1声明接口public interface Calculator { int add(int i,int j); int sub(int i,int j); int mul(int i,int j); int div(int i,int j);}5.1.2加减乘除实现类public cl
java 切面 实现日志 自定义注解 spring java Powered by 金山文档 System