美文网首页
Java 反射,动态代理

Java 反射,动态代理

作者: panzhangbao | 来源:发表于2018-12-02 09:17 被阅读10次

    定义: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
                      输出方法内容
            */
        }
    
    }
    

    相关文章

      网友评论

          本文标题:Java 反射,动态代理

          本文链接:https://www.haomeiwen.com/subject/ywadcqtx.html