zoukankan      html  css  js  c++  java
  • 架构系列——java动态代理中的InvocationHandler和Proxy,知道这些已经妥妥的了

    博主专注于Java、架构、Linux、小程序、爬虫、自动化等技术。 工作期间含泪整理出一些资料,微信搜索【程序员高手之路】,回复 【java】【黑客】【爬虫】【小程序】【面试】等关键字免费获取资料

    前言

    先赞后看,此生必赚!

    Java中动态代理的实现,主要是InvocationHandler和Proxy的使用。

    可以通过以下步骤实现一个动态代理:

    一、创建正常的接口以及实现类

    1. 接口:

    public interface People {
        public void working();
    }

    2. 实现类:

    public class Student implements People {
        
        @Override
        public void work() {
            System.out.println("正在学习...");
        }
    
    }

    二、创建一个PeopleHandler实现InvocationHandler

    public class PeopleHandler implements InvocationHandler {
        private Object obj;
        
        public PeopleHandler(Object obj) {
            this.obj = obj;
        }
    
        public Object getProxy(Object obj) {
            return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before invoke...");
            Object result = method.invoke(obj, args);
            System.out.println("after invoke...");
            return result;
        }
    
    }

    解读:

    PeopleHandler(Object obj):通过被代理对象创建handler;

    getProxy(Object obj):通过被代理对象创建代理;

    invoke(Object proxy, Method method, Object[] args):代理不直接调用invoke,而是使用正常的方法时都会走invoke方法;

    三、调用方法

    可以使用两种方式调用方法:

    1. 直接调用

    不使用代理类直接调用,直接实现业务逻辑

    2. 使用代理类调用

    使用代理类调用,间接实现业务逻辑

    public class TestProxy {
        public static void main(String[] args) {
            //1.直接调用
            System.out.println("直接调用:");
            People people = new Student();
            people.work();
            
            //2.通过代理调用
            System.out.println("
    通过代理调用:");
            PeopleHandler handler = new PeopleHandler(people);
            People proxy = (People) handler.getProxy(people);
            proxy.work();
        }
    }

    结果:

    直接调用:
    正在学习...
    
    通过代理调用:
    before invoke...
    正在学习...
    after invoke...

    四、总结

    1. 使用代理的好处

    从上面的案例可以看出,两者都可以实现正常的业务逻辑,那为啥要多此一举地使用代理类呢?

    1.1 降低耦合度

    正常逻辑work()日志的关系没那么强烈,可以对业务逻辑的各个部分进行隔离。

    1.2 提高可重用性

    如果不使用代理,需要每一次在调用work()前后都要写日志,这样的话,代码的可重用性为0!

    使用代理之后,只需要在handler的invoke()方法中写一次即可,重用性明显提高!

    2. 使用场景

    除了上面案例中的日志,还有性能统计,安全控制,事务处理,异常处理等等。

    安全控制举例

    校验用户权限,每一个菜单请求,都要判断一下请求的用户是否有该菜单权限。菜单多了,代码冗余,且容易遗漏。

    通过动态代理就可以实现为:每一个用户,每一个菜单的请求,都经过代理(proxy),由他判断是否有权限,调用者只需要调用,实现自己的逻辑,不关心权限问题。

  • 相关阅读:
    PMD安装使用
    FindBugs安装使用
    Checkstyle安装使用
    SourceMonitor的基本使用教程
    论文选题
    github for Test
    Junit的安装与使用
    安装并使用PICT,生成测试用例
    安装并使用CheckStyle/PMD与FindBug && 安装并使用SourceMonitor检测代码复杂度
    github账号 及文章选题
  • 原文地址:https://www.cnblogs.com/shuhao66666/p/12925390.html
Copyright © 2011-2022 走看看