java反射机制&动态代理
来源:互联网 发布:netgear网络存储 编辑:程序博客网 时间:2024/04/29 18:12
综合各个博客主的帖子而来,感谢以下博主!
java反射机制详解:http://www.cnblogs.com/lzq198754/p/5780331.html
java中的反射机制:http://blog.csdn.net/liujiahan629629/article/details/18013523
java中的动态代理详解:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
反射机制
1.反射机制的定义
反射机制是在运行状态中,对于任意一个类,都能够获得这个类的状态,能够访问,检测和修改它本身状态或者行为的一种能力。并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。简单来讲,就是对于任意一个类,都能在运行状态下,获得这个类的所有属性和方法;对于任何一个对象,都能够调用它的任意一个方法和属性。
2.反射机制能做什么?
- 反编译 .class->.java
- 通过反射机制访问对象的方法,属性等;
- 运行时判断任意一个对象所属的类;
- 运行时构造任意一个类的对象;
- 运行时调用任意一个对象的方法;
- 生成动态代理等;
反射机制非常强大,几乎可以不创建对象而调用另外一个对象所有东西,对应的也就有了下面的例子。可以调用的功能如下:
- 获得一个对象的类Class
- 获得这个Class之后可以获得这个类的所有的属性(返回Field数组,getDeclaredFields())以及属性相关的名字等,并设置相关的属性
- 获得这个Class之后可以获得这个类的单个属性(返回Field对象,getDeclareField(String name))
- 获得这个Class之后可以获得这个类的所有的f方法(返回Method数组,getMethods())
- 获得这个Class之后可以获得这个类的单个方法(返回Method对象,getMethod(String methodNAME,Parameter.class)如果有参数,Parameter.class)
- 获得方法的参数情况(返回Parameter[]数组,或者返回单个Paratmeter),类似于上面的情况
- 获得这个Class之后可以获得这个类的所有的构造函数(返回Constructor数组,getContructors())
- 获得这个Class之后可以获得这个类的单个构造函数,不写了,自己看api去吧,反正很多。
- 反射机制对数组进行操作Array类的很多静态方法
- 反射机制进行动态代理
3.反射机制的类以及API
java.lang.Class;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflec.Method;
java.lang.reflect.Modifier;
API我们通过一些例子来看
获得一个对象的完整的包名和类名以及类加载器
public class TestReflectGetClassName {public static void main(String[] args) {// TODO Auto-generated method stubTestReflectGetClassName t = new TestReflectGetClassName();System.out.println(t.getClass().getName()+" "+t.getClass().getClassLoader());}}
获取类,注意是类
public class TestReflectGetClass {public void getClasses() throws ClassNotFoundException{//第一种方式,使用注册的方式Class c1 = Class.forName("TestReflectGetClass");//第二种方式,使用每个类里面自带的class属性Class c2 = TestReflectGetClassName.class;//第三种方式,每个对象的getClass方法TestReflectGetClassName t = new TestReflectGetClassName();Class c3 = t.getClass();}}
实例化Class类对象
//先使用任意一种方式获得类,比如使用注册的方式Class c1 = Class.forName("TestReflectGetClass");//然后调用newInstance()方法Object trg = c1.newInstance();
获取属性,其实第一个后去class名和加载器的方式也算是获得属性的方式;
包括获得父类,获得接口(getInterfaces()),获得所有的方法,获得所有的参数等
public class TestReflectGetClassName {int a=0;int b=2;String s = "1";public static void main(String[] args) throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException {// TODO Auto-generated method stub//获得当前类的名字和类加载器TestReflectGetClassName t = new TestReflectGetClassName();System.out.println(t.getClass().getName()+" "+t.getClass().getClassLoader());Class<?> c = Class.forName("javaReflection.TestReflectGetClassName");//获得父类Class<?> parent = c.getSuperclass();System.out.println("parent's name"+parent.getName());//获得所有属性的名字Field[] fs = c.getDeclaredFields();for(Field f:fs){//获得当前域的类型System.out.print("type:"+f.getType().getName()+" ");//获得当前这个域的名字,a/b/sSystem.out.print("name:"+f.getName()+" ");//获得对象t的当前这个域的值,也可以是其他同类型对象System.out.println("value:"+f.get(t));//修改当前对象的值t,由于不是同一类型,所以只能修改为原来的值f.set(t, f.get(t));}System.out.println("--------------");//获得所有的方法Method[] ms = c.getMethods();for(Method m:ms){//获得方法名System.out.print("name:"+m.getName()+" ");//获得返回类型System.out.print("returType:"+m.getReturnType()+" ");//获得参数个数System.out.println("parameters number:"+m.getParameterCount());}}public int getA() {return a;}public void setA(int a) {this.a = a;}public int getB() {return b;}public void setB(int b) {this.b = b;}public String getS() {return s;}public void setS(String s) {this.s = s;}}
通过反射机制获取全部的构造函数并使用构造函数初始化对象
public class TestReflect { public static void main(String[] args) throws Exception { Class<?> class1 = null; class1 = Class.forName("javaReflection.User"); // 第一种方法,实例化默认构造方法,调用set赋值 User user = (User) class1.newInstance(); user.setAge(20); user.setName("Rollen"); System.out.println(user); // 结果 User [age=20, name=Rollen] // 第二种方法 取得全部的构造函数 使用构造函数赋值 Constructor<?> cons[] = class1.getConstructors(); // 查看每个构造方法需要的参数 for (int i = 0; i < cons.length; i++) { Class<?> clazzs[] = cons[i].getParameterTypes(); System.out.print("cons[" + i + "] ("); for (int j = 0; j < clazzs.length; j++) { if (j == clazzs.length - 1) System.out.print(clazzs[j].getName()); else System.out.print(clazzs[j].getName() + ","); } System.out.println(")"); } // 结果 // cons[0] (int,java.lang.String) // cons[1] (java.lang.String) // cons[2] () //这里必须按照前面的结果顺序来。 user = (User) cons[0].newInstance(20,"Rollen"); System.out.println(user); // 结果 User [age=0, name=Rollen] user = (User) cons[1].newInstance( "Rollen"); System.out.println(user); // 结果 User [age=20, name=Rollen] }}class User { private int age; private String name; public User() { super(); } public User(String name) { super(); this.name = name; } public User(int age, String name) { super(); this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User [age=" + age + ", name=" + name + "]"; }}
4.反射机制实战
在泛型Integer的ArrayList中存放一个String类型的对象
public class TestReflect { public static void main(String[] args) throws Exception { ArrayList<Integer> list = new ArrayList<Integer>(); Method method = list.getClass().getMethod("add", Object.class); method.invoke(list, "Java反射机制实例。"); System.out.println(list.get(0)); }}
通过反射机制取得并修改数组的信息
public class TestReflect3 {/*执行结果 * 数组类型: int * 数组长度 5 * 数组的第一个元素: 1 * 修改之后数组第一个元素为: 100 */public static void main(String[] args) {// TODO Auto-generated method stubint[] array = {1,2,3,4,5};Class<?> cl = array.getClass().getComponentType();System.out.println("数组类型: " + cl.getName()); System.out.println("数组长度 " + Array.getLength(array)); System.out.println("数组的第一个元素: " + Array.get(array, 0)); Array.set(array, 0, 100); System.out.println("修改之后数组第一个元素为: " + Array.get(array, 0));}}
通过反射机制修改数组大小
/* * 数组长度为: 15 *1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 *数组长度为: 8 *a b c null null null null null */public class TestReflect4 { public static void main(String[] args) throws Exception { int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int[] newTemp = (int[]) arrayInc(temp, 15); print(newTemp); String[] atr = { "a", "b", "c" }; String[] str1 = (String[]) arrayInc(atr, 8); print(str1); } // 修改数组大小 public static Object arrayInc(Object obj, int len) { Class<?> arr = obj.getClass().getComponentType(); Object newArr = Array.newInstance(arr, len); int co = Array.getLength(obj); System.arraycopy(obj, 0, newArr, 0, co); return newArr; } // 打印 public static void print(Object obj) { Class<?> c = obj.getClass(); if (!c.isArray()) { return; } System.out.println("数组长度为: " + Array.getLength(obj)); for (int i = 0; i < Array.getLength(obj); i++) { System.out.print(Array.get(obj, i) + " "); } System.out.println(); }}
动态代理--基于反射机制
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾。在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。
public interface Subject { public void doSomething(); } public class RealSubject implements Subject { public void doSomething() { System.out.println( "call doSomething()" ); } } public class ProxyHandler implements InvocationHandler { private Object proxied; public ProxyHandler( Object proxied ) { this.proxied = proxied; } public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable { //在转调具体目标对象之前,可以执行一些功能处理 //转调具体目标对象的方法 return method.invoke( proxied, args); //在转调具体目标对象之后,可以执行一些功能处理 } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import sun.misc.ProxyGenerator; import java.io.*; public class DynamicProxy { public static void main( String args[] ) { RealSubject real = new RealSubject(); Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class[]{Subject.class}, new ProxyHandler(real)); proxySubject.doSomething(); //write proxySubject class binary data to file createProxyClassFile(); } public static void createProxyClassFile() { String name = "ProxySubject"; byte[] data = ProxyGenerator.generateProxyClass( name, new Class[] { Subject.class } ); try { FileOutputStream out = new FileOutputStream( name + ".class" ); out.write( data ); out.close(); } catch( Exception e ) { e.printStackTrace(); } } }总的来说,proxy生成了一个关于指定定对象(real)的代理对象(proxySubject),这个对象继承了proxy,同时实现了被代理对象(上述的RealSubject类的对象)的所有接口(Subject接口)。因此这个代理对象能够调用被代理对象的所有方法(被代理对象的非接口实现方法无法调用,也算是个缺陷吧),调用这个方法的步骤是 proxySubject调用doSomething方法,这个doSomething 方法调用InvocatoinHandler的invoke方法,invoke方法通过method参数和一开始初始化的代理对象real调用real的doSomething方法。就是这样。
具体的实现比较难理解,源代码涉及到非常复杂的情况,有空再看。
3 0
- java反射机制&动态代理
- Java反射机制动态代理
- java反射机制与动态代理
- Java反射机制与动态代理
- JAVA的反射机制与动态代理
- JAVA反射机制与动态代理
- java反射机制和动态代理
- java反射机制与动态代理
- java反射机制与动态代理
- java反射机制与动态代理
- Java反射机制(四):动态代理
- JAVA的反射机制与动态代理
- JAVA反射机制与动态代理
- java反射机制中的动态代理
- AOP:java动态代理+反射机制
- Java学习之反射机制---动态代理
- Java 动态代理与反射机制
- JAVA的反射机制和动态代理
- 关于AngularJS的ui-router
- 多线程_生产者消费者之等待唤醒机制代码优化
- Linux-内存分析-free meminfo
- 安卓studio编辑gradle文件非常卡和远程关闭一个现有链接问题解决
- redis命令及操作记录以及redis的五种数据类型介绍
- java反射机制&动态代理
- zookeeper安装
- Linux-网络分析-netstat
- Android (1)—Activity
- 面试题之获取start到end之间的随机数
- AndroidStudio导入他人项目时报出:Error:(1, 0) Your project path contains non-ASCII characters错误
- 创建可以回调主程序接口的动态库
- Linux-网络分析-tcpdump
- 旋转数组的最小值:求中间值我竟然求错。