jdk 动态代理

简介: jdk 动态代理

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


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


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


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


为什么需要代理

1、原有功能增强


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


2、降低耦合


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


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

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


必须实现 InvocationHandler 接口;


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


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


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


需要代理的接口

1. public interface Service {
2. void send(String msg);
3. }

代理类、

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");
    }
}
相关文章
|
6月前
|
缓存 Java 数据库连接
分析JDK动态代理的实现
分析JDK动态代理的实现
41 0
|
9月前
|
Java
jdk动态代理实现原理
jdk动态代理实现原理
40 0
|
18天前
|
Java 程序员 API
浅谈JDK动态代理
浅谈JDK动态代理
33 1
|
18天前
|
Java
关于JDK动态代理
关于JDK动态代理的一些理解
15 0
|
18天前
|
设计模式 Java API
[Java]静态代理、动态代理(基于JDK1.8)
本篇文章主要是对静态代理和动态代理实现思路的简述,以示例为主,少涉及理论。 如果文中阐述不全或不对的,多多交流。
59 1
[Java]静态代理、动态代理(基于JDK1.8)
|
18天前
|
设计模式 安全 Java
深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
465 1
|
18天前
|
Java 数据安全/隐私保护
【面试问题】JDK 动态代理与 CGLIB 区别?
【1月更文挑战第27天】【面试问题】JDK 动态代理与 CGLIB 区别?
|
18天前
|
Java Linux iOS开发
Spring5源码(27)-静态代理模式和JDK、CGLIB动态代理
Spring5源码(27)-静态代理模式和JDK、CGLIB动态代理
26 0
|
10月前
|
设计模式 Java 数据安全/隐私保护
设计模式之代理模式(jdk和cglib、手撕源码、自创动态代理) 1
设计模式之代理模式(jdk和cglib、手撕源码、自创动态代理)
61 0
|
18天前
|
Java
JDK动态代理笔记整理
JDK动态代理笔记整理