【Java】反射与动态代理


反射是什么?

通过反射可以获取一个类的成员(字段、方法、构造)
举例:IDEA 中查看一个类/方法要传入什么参数 就是通过反射 还有调用一个类/对象内部的方法,点.出来的方法列表 就是反射出来的。

  • 获取任意一个类中的所有信息
  • 结合配置文件动态创建对象

动态代理是什么?

防止侵入式修改 (也就是直接修改一个类 导致程序崩溃)。
代理可以无侵入式的给对象增强其他的功能。
流程

对象有什么方法 需要被代理,代理就一定有对应的方法。(通过接口通知代理 要代理什么方法)
效果


一、获取class字节码文件的三种方式

  1. Class.forName(“类的全类名”);
  2. 类名.class; 属性
  3. 对象.getClass();
        //1.第一种方式
        // 全类名:包名+类名
        //使用场景:最常用,当类被创建编译后就可以用
        Class aClass = Class.forName("com.reflect1.Student");
        System.out.println(aClass);//class com.reflect1.Student

        //2.第二种方式
        //一般就是当作参数传递,比如多线程中的同步锁使用
        Class aClass1 = Student.class;
        System.out.println(aClass == aClass1);//true

        //3.第三种方式
        //创建了这个类的对象后,就可以用这个方法
        Student student = new Student();
        Class aClass2 = student.getClass();
        System.out.println(aClass1 == aClass2);//true

二、反射获取构造方法 (Constructor)

常用方法

三、反射获取成员变量 (Field)

常用

四、反射获取成员方法 (Method)

方法

五、动态代理分析与代码实现

  • 代理里面存放需要被代理的方法。
  • 通过接口 存放要被代理的方法,对象和代理都要实现该接口
    代理
    实体类:
    实体
    接口:
public interface Start {
    String sing(String song);
    void dance();
}

代理:

public class ProxyUtil {
    public static Start createProxy(BigStart bigStart) {

        //参数一:指定用哪个类加载器,去加载生成的代理对象
        //参数二:有哪些接口
        //参数三:指定生成的代理对象要做什么
        Start start = (Start) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{Start.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /*
                 * 参数一  代理的对象
                 * 参数二  需要执行的方法
                 * 参数三  调用方法需要的参数
                 * */
                if ("sing".equals(method.getName())) {
                    System.out.println("开始唱歌吧!");
                } else if ("dance".equals(method.getName())) {
                    System.out.println("开始跳舞吧!");
                }

                return method.invoke(bigStart, args);
            }
        });

        return start;
    }
}

测试:

        BigStart bigStart = new BigStart("鸡哥");
        Start start = ProxyUtil.createProxy(bigStart);

        String result = start.sing("只因你太美");
        System.out.println(result);

        start.dance();

流程图


综合练习

保存任意对象数据

public class ReflectDemo1 {
    public static void main(String[] args) throws IllegalAccessException, IOException {
        Student s = new Student("张三", 18);
        saveObject(s);
    }
    private static void saveObject(Object obj) throws IllegalAccessException, IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("A-SocketNet\\a.txt"));

        Class<?> aClass = obj.getClass();
        Field[] df = aClass.getDeclaredFields();
        for (Field field : df) {
            field.setAccessible(true);
            String name = field.getName();
            Object value = field.get(obj);
            System.out.println(name+"="+value);
            bw.write(name+"="+value);
            bw.newLine();
        }

        bw.close();
    }
}

效果

利用反射动态的创建对象和运行方法

    /*
        反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
    */
        //从配置文件中获取 全类名与要调用的方法
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream("A-SocketNet\\prop.properties");
        prop.load(fis);
        System.out.println(prop);//{classname=com.reflect2.Teacher, method=teach}

        //配置文件中获取数值
        Object classname = prop.get("classname");
        Object method = prop.get("method");

        Class aClass = Class.forName(String.valueOf(classname));

        // 反射创建有参构造
        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, double.class);
        Object o1 = declaredConstructor.newInstance("1", 2.9);
        System.out.println(o1);

        // 反射创建无参构造
        Constructor constructor = aClass.getDeclaredConstructor();
        Object o = constructor.newInstance();
        System.out.println(o);

        // 反射 调用 方法 
        Method declaredMethod = aClass.getDeclaredMethod(String.valueOf(method));
        declaredMethod.invoke(o);

配置文件:
配置文件
相关实体类:
实体类
运行效果:
效果

总结

反射:
总结

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道格维克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值