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

package com.pan;

public interface PanInterface{

  // 接口方法
  public String getPanMethod();

}
package com.pan;

public class PanImplement implements PanInterface{

    @Override
    public String getPanMethod() {
        return "输出方法内容";
    }
}
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;
    }
}
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
                  输出方法内容
        */
    }

}
上一篇下一篇

猜你喜欢

热点阅读