jdk 动态代理

命运对每个人都是一样的,不一样的是各自的努力和付出不同,付出的越多,努力的越多,得到的回报也越多,在你累的时候请看一下身边比你成功却还比你更努力的人,这样,你就会更有动力。

导读:本篇文章讲解 jdk 动态代理,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

就是当你写了一个接口,里面有方法,然后写了实现类实现方法,完成方法逻辑,然后有一天,想对这个方法进行修改,但是不想改源码,所以有两种方式可以实现。第一种是静态代理,创建一个类继承实现类,然后对方法进行修改,这样太局限,因为只能针对特定的类增强方法,有100个实现类就要创建100个子类去实现。第二种方式是动态代理,可以动态地生成代理类,这是可以接受的。

当现有的类的代码只能满足一些基本的功能,而这些功能满足不了新需求,但又不能改动以前的代码,这时候就可以考虑使用代理,通过代理类,扩展原有类的功能,客户端访问的入口只是聪目标对象切换到代理对象而已;

JDK动态代理是有JDK提供的工具类Proxy实现的,动态代理类是在运行时生成指定接口的代理类,每个代理实例(实现需要代理的接口)都有一个关联的调用处理程序对象,此对象实现了InvocationHandler,最终的业务逻辑是在InvocationHandler实现类的invoke方法上。

也即是在invoke方法上可以实现原方法中没有的业务逻辑,相当于spring aop的@Before、@After等注解。

为什么需要代理

1、原有功能增强

举例来说,当现有的类的代码只能满足一些基本的功能,而这些功能满足不了新需求,但又不能改动以前的代码,这时候就可以考虑使用代理,通过代理类,扩展原有类的功能,客户端访问的入口只是聪目标对象切换到代理对象而已;

2、降低耦合

在程序设计时,需要遵循一个叫做“单一职责”的原则,该原则要求每个类功能尽可能单一,为什么要单一,因为只有功能单一这个类被改动的可能性才会最小。

现在突然接到需求,需要对现有类的增删改这样的事务性操作增加审计日志,很多人第一想到的是给每个增删改的地方增加日志,如果这样的类特别多,这就很折腾了,比较好的办法就是,使用代理类,在不对原来类修改的基础上,进行日志功能的扩展即可(spring aop功能即是如此);

JDK 动态代理是基于拦截器和反射实现的,不需要第三方库支持,只需要 JDK 环境即可

  • 必须实现 InvocationHandler 接口;

  • 使用 Proxy.newProxyInstance 产生代理对象;

  • 被代理的对象必须要实现接口;

  • 内部采用asm技术动态生成字节码;

需要代理的接口

public interface Service {
    void send(String msg);
}

代理类、

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

public class InvocationHandle<T> implements InvocationHandler {

    private T target;

    public InvocationHandle(T target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("之前执行"+method.getName());
        Object invoke = method.invoke(target, args);
        System.out.println("之后执行"+method.getName());
        return invoke;
    }
}

获取代理对象的工厂类

import java.lang.reflect.Proxy;

public class ProxyFactory {
    public static <T extends Service> Service getProxy(T target){
        Class<? extends Service> aClass = target.getClass();
        return (Service) Proxy.newProxyInstance(aClass.getClassLoader(),aClass.getInterfaces(),new InvocationHandle<>(target));
    }//类加载获得应用类加载器,class文件可以任意
}

主函数

public class test {
    public static void main(String args[]) throws Exception {
//        Service proxy = ProxyFactory.getProxy(new Service() {
//            @Override
//            public void send(String msg) {
//                System.out.println(msg);
//            }
//        });
        Service proxy = ProxyFactory.getProxy(msg -> System.out.println(msg));
        proxy.send("hello");


    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/143074.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!