JAVASE基础模块四十三( 反射来获取成员变量 反射来获取成员方法 反射越过泛型机制 通过配置文件来进行方法的调用 提高容错率与代码复用性 用反射给某个对象成员变量设置值 反射与代理

JAVASE基础知识模块四十三( 反射来获取成员变量 反射来获取成员方法 反射越过泛型机制 通过配置文件来进行方法的调用 提高容错率与代码复用性 用反射给某个对象成员变量设置值 反射与代理 静态代理 动态代理)

反射

  • JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
  • 对于任意一个对象,都能够调用它的任意一个方法和属性
  • 这种动态获取类的信息以及动态调用对象的方法的功能称为java语言的反射机制
  • 要想解剖一个类, 必须先要获取到该类的字节码文件对象
  • 而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象

反射来获取成员变量

  • 获取全部的成员变量
    1. 获取所有的公共的字段对象数组
    2. 获取所有的字段对象数组,包括私有字段
获取所有成员变量
public Field[] getFields() 获取所有的成员变量包含从父类继承过来的
public Field[] getDeclaredFields() 获取所有的成员变量 包含私有的 也包含从父类继承过来的成员变量
import java.lang.reflect.Field;

public class ChengYuan {
    public static void main(String[] args) {
        try {
            Class<?> a = Class.forName("FanShe.X1.Stu");
            Field[] f = a.getFields();
            for (Field ff : f) {
                System.out.println(ff);
            }
            System.out.println("==================================");
            Field[] d = a.getDeclaredFields();
            for (Field dd : d) {
                System.out.println(dd);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }}

class Stu{
    public String name;
    private int age;
    protected char sex;

}
运行结果:
public java.lang.String FanShe.X1.Stu.name
==================================
public java.lang.String FanShe.X1.Stu.name
private int FanShe.X1.Stu.age
protected char FanShe.X1.Stu.sex
  • 获取指定的成员变量与通过反射获取成员变量并使用
    1. 获取指定的字段对象
    2. 通过反射给字段设置值
    3. 给私有字段设置值,取消私有的语法检查
获取单个成员变量
public Field getField(String name)
public Field getDeclaredField(String name)
package FanShe.X1;
import java.lang.reflect.Field;
public class ChengZhi {
    public static void main(String[] args) {
        try {
            Class<?> a = Class.forName("FanShe.X1.Stude");
            Field name = a.getField("name");
            System.out.println(name);
            Field age = a.getDeclaredField("age");
            System.out.println(age);
            System.out.println("===============================");
            Object o = a.newInstance();
            name.set(o,"san");
            Object o1 = name.get(o);
            System.out.println(o1);
            System.out.println("============================");
            Field age1 = a.getDeclaredField("age");
            age1.setInt(o,100);
            Object o2 = age1.get(o);
            System.out.println(o2);
            System.out.println("============================");
            Field he = a.getDeclaredField("he");
            he.setAccessible(true);
            he.setDouble(o,33.77);
            Object o3 = he.get(o);
            System.out.println(o3);
        } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }

    }

}
class Stude{
    public String name;
    protected int age;
    private double he;
    char sex;
}
运行结果:
===============================
san
============================
100
===========================
33.77

反射来获取成员方法

  • 获取所有成员方法
    1. getMethods() 获取所有的公共的方法对象 包括父类的公共方法
    2. getDeclaredMethods()获取所有的方法对象 包括私有的方法 不获取父类的方法对象
public Method[] getMethods() 获取所有的公共的成员方法不包含私有的 包含从父类继承过来的过来的公共方法
public Method[] getDeclaredMethods()  获取自己的所有成员方法 包含私有的
package FanShe.X1;

import java.lang.reflect.Method;
import java.util.Arrays;

public class FangFa {
    public static void main(String[] args) {
        try {
            Class<?> a = Class.forName("FanShe.X1.Student");
            Method[] m = a.getMethods();
            System.out.println(Arrays.toString(m));
            System.out.println("=======================================");
            Method[] d = a.getDeclaredMethods();
            System.out.println(Arrays.toString(d));

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}

class Student {

    public void xc() {
        System.out.println("公有方法");
    }

    private void xc1(String name) {
        System.out.println("私有方法");
    }

    protected void xc2(String name, int age) {
        System.out.println("保护方法");
    }

    void xc3(String name, int age) {
        System.out.println("缺省方法");
    }

    String xc4(String name, int age) {
        return "返回值方法";
    }
}
运行结果:
[public void FanShe.X1.Student.xc(), public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
=======================================
[java.lang.String FanShe.X1.Student.xc4(java.lang.String,int), void FanShe.X1.Student.xc3(java.lang.String,int), private void FanShe.X1.Student.xc1(java.lang.String), protected void FanShe.X1.Student.xc2(java.lang.String,int), public void FanShe.X1.Student.xc()]
  • 获取单个成员方法
    1. 获取指定的方法对象
参数1: 方法名称  参数2:方法行参的class 对象
	public Method getMethod(String name,Class<?>... parameterTypes) 获取单个的方法 不包含私有的
	public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取单个方法包括私有的
package FanShe.X1;

import java.lang.reflect.Method;

public class FanZhi {
    public static void main(String[] args) {
        try {
            Class<?> a = Class.forName("FanShe.X1.Stud");
            Method m = a.getMethod("xc");
            System.out.println(m);
            Method d = a.getDeclaredMethod("xc1",String.class);
            System.out.println(d);

        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        }

    }
}

class Stud {

    public void xc() {
        System.out.println("公有方法");
    }

    private void xc1(String name) {
        System.out.println("私有方法");
    }

    protected void xc2(String name, int age) {
        System.out.println("保护方法");
    }

    void xc3(String name, int age) {
        System.out.println("缺省方法");
    }

    String xc4(String name, int age) {
        return "返回值方法";
    }

}
运行结果:
public void FanShe.X1.Stud.xc()
private void FanShe.X1.Stud.xc1(java.lang.String)
  • 通过反射获取无参无返回值成员方法并使用
    1. 获取指定的方法对象
    2. 取消私有权限检查
    3. 让方法调用执行
package FanShe.X1;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class DiaoYong {
    public static void main(String[] args) {
        try {
            Class<?> a = Class.forName("FanShe.X1.Studen");
            Method m = a.getMethod("xc");
            m.setAccessible(true);
            Constructor<?> dd = a.getDeclaredConstructor();
            dd.setAccessible(true);
            Object o =dd.newInstance();
            m.invoke(o);
            System.out.println("=============================");
            Method d = a.getDeclaredMethod("xc1", String.class);
            d.setAccessible(true);
            d.invoke(o, "xxx");
            Method d1 = a.getDeclaredMethod("xc2", String.class, int.class);
            d1.invoke(o, "xxx", 33);
            Method t = a.getDeclaredMethod("test", String.class, int.class);
            t.setAccessible(true);
            t.invoke(o,"popo",77);

        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}

class Studen {
    private Studen() {
    }

    public void xc() {
        System.out.println("公有方法");
    }

    private void xc1(String name) {
        System.out.println("私有方法" + name);
    }

    protected void xc2(String name, int age) {
        System.out.println("保护方法" + name + "===" + age);
    }

    void xc3(String name, int age) {
        System.out.println("缺省方法");
    }

    String xc4(String name, int age) {
        return "返回值方法";
    }

    private void test(String name, int age) {
        System.out.println("私有的方法调用了" + name + "==" + age);
    }
}

运行结果:
公有方法
=============================
私有方法xxx
保护方法xxx===33
私有的方法调用了popo==77

反射的一些应用

反射越过泛型机制
  • 需求:我这个集合的泛型声明为了String类型,但是我想在集合中添加Integer类型的元素
    通过反射机制,越过了泛型检测
  • 泛型只在编译期有效,在运行期就擦除了
package FanShe.X2;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class FanXing {
    public static void main(String[] args) {
        ArrayList<String> a = new ArrayList<>();
        a.add("ccc");
        a.add("xxx");
        Class<? extends ArrayList> ac = a.getClass();
        try {
            Method add = ac.getMethod("add", Object.class);
            add.invoke(a,500);
            System.out.println(a);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
运行结果:
[ccc, xxx, 500]

通过配置文件来进行方法的调用 提高容错率与代码复用性

  • 文件内容
catName=FanShe.X2.Cat
cName=eat
dogName=FanShe.X2.Dog
dName=eat
  • 代码
package FanShe.X2;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class Fan {
    public static void main(String[] args) {
        Properties p = new Properties();
        try {
            p.load(new FileInputStream("src\\FanShe\\X2\\p.properties"));
            Class<?> c = Class.forName(p.getProperty("catName"));
            Constructor<?> d = c.getDeclaredConstructor();
            d.setAccessible(true);
            Object o = d.newInstance();
            Method cName = c.getDeclaredMethod(p.getProperty("cName"));
            cName.invoke(o);
            Class<?> c1 = Class.forName(p.getProperty("dogName"));
            Constructor<?> d1 = c1.getDeclaredConstructor();
            d1.setAccessible(true);
            Object o1 = d1.newInstance();
            Method cName1 = c1.getDeclaredMethod(p.getProperty("dName"));
            cName1.invoke(o1);


        } catch (IOException | ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

class Dog {
    public void eat() {
        System.out.println("猫吃鲸鱼");
    }
}

class Cat {
    public void eat() {
        System.out.println("狗吃太阳");
    }
}
运行结果:
狗吃太阳
猫吃鲸鱼

用反射给某个对象 成员变量设置值

  • 代码
package FanShe.X2;

import java.lang.reflect.Field;

public class SheZhi {
    public static void main(String[] args) {
        Student2 s = new Student2();
        GongJu.setProperty(s, "name", "xxxx");
        GongJu.setProperty(s, "age", 333);
        Object name = GongJu.getProperty(s, "name");
        Object age = GongJu.getProperty(s, "age");
        System.out.println(name);
        System.out.println(age);


    }
}

class GongJu {
    //给某个对象 成员变量设置值
    public static void setProperty(Object o, String p, Object i) {
        Class<?> a = o.getClass();
        try {
            Field d = a.getDeclaredField(p);
            d.setAccessible(true);
            d.set(o, i);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static Object getProperty(Object o, String p) {
        Class<?> a = o.getClass();
        Object o1 = null;
        try {
            Field d = a.getDeclaredField(p);
            d.setAccessible(true);
            o1 = d.get(o);
            return o1;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return o1;
    }
}

class Student2 {
    private String name;
    private int age;
}
运行结果:
xxxx
333

反射与代理

代理
  • 概述:本来应该自己做的事情 却请了别人来做 被请的人就是代理对象
  • 分类
    1. 静态代理
    2. 动态代理:在程序运行过程中产生的这个对象

案例

需求

  • 增删改查以及敏感操作的记录
package FanShe.X3;

public interface UserDao {
    public abstract void insert();
    public abstract void delete();
    public abstract void update();
    public abstract void query();
}
  • 普通处理方法
package FanShe.X3;

public class UserDaoImpl implements UserDao {
    @Override
    public void insert() {
    	System.out.println("权限校验");
        System.out.println("增加用户功能");
        System.out.println("日志记录");
    }

    @Override
    public void delete() {
        System.out.println("权限校验");
        System.out.println("删除用户功能");
        System.out.println("日志记录");
    }

    @Override
    public void update() { 
        System.out.println("权限校验");
        System.out.println("修改用户功能");
        System.out.println("日志记录");
    }

    @Override
    public void query() {
        System.out.println("权限校验");
        System.out.println("查找用户功能");
        System.out.println("日志记录");

    }
}

静态代理

package FanShe.X3;

public class UserDaoStaticClass implements UserDao {
    private UserDaoImpl u = new UserDaoImpl();

    @Override
    public void insert() {
        System.out.println("权限校验");
        u.insert();
        System.out.println("日志记录");
    }

    @Override
    public void delete() {
        System.out.println("权限校验");
        u.insert();
        System.out.println("日志记录");
    }

    @Override
    public void update() {
        System.out.println("权限校验");
        u.insert();
        System.out.println("日志记录");
    }

    @Override
    public void query() {
        System.out.println("权限校验");
        u.insert();
        System.out.println("日志记录");
    }
}

动态代理

  • 动态代理 要求:必须要有接口

  • CGLIB代理:不需要有接口

  • 程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
    在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,
    通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。
    我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象
    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    最终会调用InvocationHandler的方法 InvocationHandler Object invoke(Object proxy,Method method,Object[] args)
    
  • UserDao uu= (UserDao) Proxy.newProxyInstance(u.getClass().getClassLoader(), u.getClass().getInterfaces(), new InvocationHandler() 
    ========================================================================
     newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
     loader 类加载器,用的是和被代理对象同一个加载器 固定写法
     interfaces 代理对象所实现的所有接口的Class类型的数组 固定写法
     InvocationHandler 接口,让你用来做增强的
    
  •  public Object invoke(Object proxy, Method method, Object[] args) 
     ========================================================================
                 proxy 代理对象
                 method 方法对象
                 args 方法对象的参数的数组
    
  • 类 Proxy 代理类,可以通过反射机制,帮你创建换一个代理对象。
    newProxyInstance(ClassLoader loader, Class < ? >[]interfaces, InvocationHandler h)
      返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
    
  • 步骤

    1. 获取代理对象
    2. 产生代理对象
    3. 方法调用会被转发到该类的invoke()方法
  • 总结

		*  特点:字节码随用随创建,随用随加载
         *  作用:不修改源码的基础上对方法增强
         *  分类:
         *      基于接口的动态代理
         *      基于子类的动态代理
         *  基于接口的动态代理:
         *      涉及的类:Proxy
         *      提供者:JDK官方
         *  如何创建代理对象:
         *      使用Proxy类中的newProxyInstance方法
         *  创建代理对象的要求:
         *      被代理类最少实现一个接口,如果没有则不能使用
         *  newProxyInstance方法的参数:
         *      ClassLoader:类加载器
         *          它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
         *      Class[]:字节码数组 
         *          它是用于让代理对象和被代理对象有相同方法。固定写法。
         *      InvocationHandler:用于提供增强的代码
         *          它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
         *          此接口的实现类都是谁用谁写。
  • new InvocationHandler()方法
new InvocationHandler() {
                    /**
                     * 作用:执行被代理对象的任何接口方法都会经过该方法
                     * 方法参数的含义
                     * @param proxy   代理对象的引用
                     * @param method  当前执行的方法
                     * @param args    当前执行方法所需的参数
                     * @return        和被代理对象方法有相同的返回值
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    }
                }
  • 代码
package FanShe.X3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Prox {
    /**
     *
     * @param u 被代理对象
     * @return 返回的是代理对象
     */
    public static UserDao getUserDao(UserDao u) {
UserDao uu= (UserDao) Proxy.newProxyInstance(u.getClass().getClassLoader(), u.getClass().getInterfaces(), new InvocationHandler() {
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               System.out.println("代理方法已执行");
               Object in=null;
               if(method.getName().equals("insert")){
                   System.out.println("权限校验");
                   in=method.invoke(u);
                   System.out.println("日志记录");
               }
               return in;
           }
       });
       return uu;
    }
}

  • 测试与结果
package FanShe.X3;

public class Test {
    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();
        UserDao proxy = Prox.getUserDao(userDao);
        proxy.insert();
        System.out.println("===================");
        proxy.update();
    }
}
运行结果:
代理方法已执行
权限校验
增加用户功能
日志记录
===================
代理方法已执行

待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值