在学习Spring框架的AOP(面向切面编程)过程中,发现其实现原理就是动静代理模式和反射。
反射:
将类的各个组成部分封装成其余对象。(成员变量、构造方法、成员办法)
益处
- 在程序运行过程中,能够操作这些对象实现一些操作。
- 能够对程序进行解耦,进步程序的可扩展性。
反射的应用:
获取Class对象:
获取Class对象的起因:当你要应用反射机制去操作这些封装对象的时候,首先是要获取到字节码Class对象
获取Class对象的形式:
- Class.forName("全类名"):将字节码文件加载进内存,返回Class对象(个别用在配置文件,将类名定义在配置文件外面。读取文件)
- 类名.class:通过类名的属性class获取
- 对象.getClass():getClass()办法在object类中定义(个别用于曾经有一个对象,想获取它的字节码)
Class对象性能:
获取成员变量:
1. Field[] getFields() //获取所有public润饰的成员变量 2. Field getField(String name) //获取指定名称的public润饰的成员变量 3. Field[] getDeclaredFields() //获取所有的成员变量,不思考修饰符 4. Field getDeclaredFields(String name) //获取指定名称的成员变量,不思考修饰符 Field:成员变量 操作: 1.设置值: void set(Object obj,Object value) 2.获取值 get(Object obj) 3.疏忽拜访权限修饰符的安全检查 setAccessible(true):暴力反射
获取构造方法:
1. Constructor<?>[] getConstrucors() //获取public润饰无参构造方法2. Constructor<T>[] getConstrucors(类<?>...parameterTypes)//获取指定参数的public润饰有参构造方法3. Constructor<T>[] getDeclaredConstrucors(类<?>...parameterTypes)//获取所有的指定参数类型的有参构造方法4. Constructor<?>[] getDeclaredConstrucors()//获取所有有参构造方法 Constructor:构造方法 T newInstance(Object... initargs)
获取成员办法:
1. Method[] getMethods()2. Method getMethod(String name,类<?>...parameterTypes)3. Method getDeclaredMethods()4. Method getDeclaredMethod(String name,类<?>...parameterTypes) Method:办法对象 执行办法: Object invoke(Object obj,Object...args) 获取办法名称: String getName:获取办法名
例子:
根本办法:
首先轻易创立一个类
package com.yuan.bean;public class Person { private String name; public Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + ''' + ", age=" + age + '}'; } public void eat(){ System.out.println("干饭"); }}
接下来通过下面介绍的办法,综合起来使用一下:
public class test01 { public static void main(String[] args) throws Exception { //办法中可能呈现多处异样,先抛个大的异样//获取Class类对象 Class cls = Class.forName("com.yuan.bean.Person"); /* 其余两种办法 Class<Person> personClass = Person.class; Person p = new Person(); Class cls = p.getClass(); */ //获取类成员变量 Field[] fields = cls.getFields(); for(Field filed:fields){ System.out.println(filed.getType()+" "+filed.getName()); //class java.lang.Integer age } //获取类构造方法 Constructor constructor = cls.getConstructor(); Person o = (Person) constructor.newInstance();//通过结构器的newInstance()创立Person类对象 //获取类成员办法 Method method = cls.getMethod("eat"); method.invoke(o);//通过method的invoke()办法调用成员办法 /*干饭*/ }}
写一个“框架”,能够帮咱们创立任意类的对象,并且执行其中任意办法:(能够练个手)
1. 首先在src目录下创立一个properties配置文件:
(外面放咱们要创建对象的类门路,以及要调用的类办法)
className=com.yuan.bean.PersonmethodName=eat
2.编写测试方法
public class ReflectTest { public static void main(String[] args) throws Exception { //加载配置文件 Properties pro = new Properties();//创立Properties对象 ClassLoader classLoader = ReflectTest.class.getClassLoader();//通过类对象 获取类加载器getClassLoader() InputStream is = classLoader.getResourceAsStream("pro.properties");//通过类加载器获取配置文件的字节输出流对象 pro.load(is);//加载文件 //获取配置文件中加载的数据 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); //加载该类进内存,获取Class类对象 Class cls = Class.forName(className); //获取构造方法 Constructor constructor = cls.getConstructor(); //通过构造方法创建对象 Object o = constructor.newInstance(); //获取成员办法 Method method = cls.getMethod(methodName); //调用成员办法 method.invoke(o); } }
后续:
这些也只是根本总结了反射的基本概念和办法,通过反射,咱们能够不通过new的形式去创立一个新的对象,能够通过反射获取一个类的成员变量、构造方法、成员办法。能够通过操作一个类,去通过获取到的类的构造方法来创建对象,以及调用类的成员办法,批改类的成员变量的值。
在学习Spring框架中,AOP使用到了java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现动静代理。所以对于反射概念的相熟是非常有必要的。