Java 反射,动态代理
2018-12-02 本文已影响10人
panzhangbao
定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
1. 访问构造方法
Test1 test1 = new Test1("10", "20", "30");
Class<? extends Test1> test1Class = test1.getClass();
// 获得所有构造方法
Constructor[] deciaredConstructors = test1Class.getDeclaredConstructors();
// 遍历构造方法
for (int i = 0; i < deciaredConstructors.length; i++) {
Constructor<?> constructor = deciaredConstructors[i];
System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs());
System.out.println("该构造方法的入口参数类型依次为:");
Class[] parameterTypes = constructor.getParameterTypes(); // 获取所有参数类型
for (int j = 0; j < parameterTypes.length; j++) {
System.out.println(" " + parameterTypes[j]);
}
System.out.println("该构造方法可能抛出的异常类型为:");
// 获取所有可能抛出的异常信息类型
Class[] exceptionTypes = constructor.getExceptionTypes();
for (int j = 0; j < exceptionTypes.length; j++) {
System.out.println(" " + exceptionTypes[j]);
}
Test1 test1_1 = null;
while (test1_1 == null) {
try {
// 如果该成员变量的访问权限为 private ,则抛出异常,即不允许访问
if (i == 2) { // 通过执行默认无参构造方法创建对象
test1_1 = (Test1) constructor.newInstance();
} else if (i == 1) { // 通过执行具有两个参数的构造方法创建对象
test1_1 = (Test1) constructor.newInstance("7", "5");
} else {
Object[] parameters = new Object[]{new String[]{"100", "200", "300"}};
test1_1 = (Test1) constructor.newInstance(parameters);
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (test1_1 != null){
test1_1.print();
}
}
2. 获取成员变量
Test2 test2 = new Test2();
Class test2Class = test2.getClass();
// 获取所有成员变量
Field[] declaredFields = test2Class.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) { // 遍历成员变量
Field field = declaredFields[i];
Class fieldType = field.getType();
System.out.println("成员变量类型为:" + fieldType);
boolean isTurn = true;
while (isTurn){
// 如果该成员变量的访问权限为 private ,则抛出异常
try {
isTurn = false;
// 获取成员变量值
System.out.println("修改前的值为:" + field.get(test2));
// 判断成员是否为 int 型
if (fieldType.equals(int.class)){
System.out.println("利用方法 setInt() 修改成员变量的值");
field.setInt(test2, 110);
}
} catch (IllegalAccessException e) {
// e.printStackTrace();
System.out.println("在设置成员变量值时抛出异常,下面执行 setAccessible() 方法");
field.setAccessible(true); // 设置为允许访问
isTurn = true;
}
}
}
3. 获取方法
Test3 test3 = new Test3();
Class test3Class = test3.getClass();
// 获取所有方法
Method[] declaredMethods = test3Class.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++){ // 遍历方法
Method method = declaredMethods[i];
System.out.println("方法名称为:" + method.getName()); // 获得方法名称
System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs());
// System.out.println("入口参数类型:" + method.getParameterTypes());
// 获得方法返回类型
System.out.println("返回类型为:" + method.getReturnType());
}
4. 获取包名、类名
Person person = new Person();
System.out.println(person.getClass().getName()); // print: com.pan.Person
5. 实例化 Class 类对象
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;
class1 = Class.forName("com.pan.Person"); // 一般采用这种形式
class2 = new Person().getClass();
class3 = Person.class;
System.out.println("类名称 " + class1.getName()); // print: 类名称 com.pan.Person
System.out.println("类名称 " + class2.getName());
System.out.println("类名称 " + class3.getName());
6. 反射机制的调用
// 通过反射机制调用某个类的方法
Class<?> personClass = Class.forName("com.pan.Person");
Method method = personClass.getMethod("eat", String.class);
method.invoke(personClass.newInstance(), "小鱼"); // print: Person eat 小鱼
// 通过反射机制操作某个类的属性
Class<?> personClass = Class.forName("com.pan.Person");
Object object = personClass.newInstance();
// 可以直接对 private 的属性赋值
Field field = personClass.getDeclaredField("name");
field.setAccessible(true);
field.set(object, "小潘");
System.out.println(field.get(object));
7. 动态代理 - 起到拦截方法作用 - AOP
- PanInterface.java
package com.pan;
public interface PanInterface{
// 接口方法
public String getPanMethod();
}
- PanImplement.java
package com.pan;
public class PanImplement implements PanInterface{
@Override
public String getPanMethod() {
return "输出方法内容";
}
}
- PanInvocationHandler.java
package com.pan;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PanInvocationHandler implements InvocationHandler{
private Object target;
PanInvocationHandler(){
super();
}
PanInvocationHandler(Object target){
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getPanMethod".equals(method.getName())){
System.out.println("before: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("after: " + method.getName());
return result;
}
Object result = method.invoke(target, args);
return result;
}
}
- Main.java
package com.pan;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) throws Exception {
PanInterface panInterface = new PanImplement();
final ClassLoader classLoader = panInterface.getClass().getClassLoader();
Class<?>[] interfaces = panInterface.getClass().getInterfaces();
InvocationHandler invocationHandler = new PanInvocationHandler(panInterface);
PanInterface panInterfaceProxy = (PanInterface) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
System.out.println(panInterfaceProxy.getPanMethod());
/**print:
before: getPanMethod
after: getPanMethod
输出方法内容
*/
}
}