代理模式
通过代理控制对象的访问,可以在这个对象调用方法之前、调用方法之后去处理/添加新的功能。(也就是AOP的实现)
代理在原有代码乃至原业务流程都不修改的情况下,直接在业务流程中切入新代码,增加新功能,这也和Spring的(面向切面编程)很相似
应用场景:SpringAOP、日志打印、异常处理、事务控制、权限控制等
-
静态代理
简单代理模式,是动态代理的理论基础。常见使用在代理模式
/* 接口类 */ public class UserDao { public void Save(){ System.out.println("Save User Data"); } }
/* 代理类 */ public class UserProxy extends UserDao{ private UserDao user; public UserProxy(UserDao user){ this.user = user; } public void Save(){ System.out.println("Open transaction"); this.user.Save(); System.out.println("close transaction"); } }
/* 调用 */ public class Demo { public static void main(String[] args){ UserDao u = new UserDao(); UserProxy userProxy = new UserProxy(u); userProxy.Save(); } }
- 缺点:每个需要代理的对象都需要自己重复编写代理
- 优点:但是可以面相实际对象或者是接口的方式实现代理
-
JKD动态代理
基于接口的动态代理技术·:利用拦截器(必须实现invocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,从而实现方法增强
/* 接口 */ public interface IUserDao { void save(); }
/* 接口实现类 */ public class UserDaoImpl implements IUserDao { @Override public void save() { System.out.println("Save User Data"); } }
/* 代理类 */ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //每次生成动态代理类对象时实现InvocationHandler接口的调用处理器对象 public class InvocationHandlerImpl implements InvocationHandler{ //业务类实现类对象,用来调用具体的方法 private Object target; //通过构造传入目标对象 public InvocationHandlerImpl(Object target){ this.target = target; } //动态代理实际运行得方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("调用开始处理"); /* method.invoke(obj, args)方法是以反射的方式来创建对象的, 第一个参数obj是要创建的对象, 第二个args是构成方法的参数,决定创建对象使用哪个构造函数 */ Object result = method.invoke(target, args); System.out.println("调用结束处理"); return result; } }
/* 调用 */ public class Test { public static void main(String[] args){ //被代理对象 IUserDao uerDaoImpl = new UserDaoImpl(); InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(uerDaoImpl); //类加载器 ClassLoader loader = uerDaoImpl.getClass().getClassLoader(); Class<?>[] interfaces = uerDaoImpl.getClass().getInterfaces(); //主要装载器、一组接口及调用处理动态代理实例 IUserDao newProxyInstance = (IUserDao)Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl); newProxyInstance.save(); } }
- 缺点:必须是面向接口,目标业务类必须实现接口
- 优点:不用关心代理类,只需要在运行阶段才指定代理哪一个对象
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)