联系我们contact

电 话:13902182895
联 系 人:张经理
地  址:天津市开发区第三大街豪威大厦1602
 

首页 > 新闻中心 > java反射机制&动态代理

新闻中心

java反射机制&动态代理

    时间:2018-10-10


【转载】


综合各个博客主的帖子而来,感谢以下博主!


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 stub


TestReflectGetClassName 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/s


System.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 stub


int[] 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方法。就是这样。


具体的实现比较难理解,源代码涉及到非常复杂的情况,有空再看。


 

上一篇:java实现常见排序算法

下一篇:企业的根本目标及其内涵(二)

天津红翔吉瑞是天津市一家正规的天津软件开发公司,从事专业的软件开发业务

首页 公司简介 新闻中心 案例中心 联系我们
天津红翔吉瑞网络科技发展有限公司 版权所有 津ICP备16005209号-2   电话:13902182895 联系人:张经理   地址:天津市开发区第三大街豪威大厦1602