就是当你写了一个接口,里面有方法,然后写了实现类实现方法,完成方法逻辑,然后有一天,想对这个方法进行修改,但是不想改源码,所以有两种方式可以实现。第一种是静态代理,创建一个类继承实现类,然后对方法进行修改,这样太局限,因为只能针对特定的类增强方法,有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