静态代理
静态代理也可以看做是代理模式,屏蔽了对真实对象的感知,处理或者调用方法时无需真实对象,只要与代理对象交互即可。主要用于由于安全或者其他原因隐藏真实访问对象,或者是为了提升性能对真实对象进行延迟加载等操作。
代码实例如下:
- 定义一个接口
/** * 账户接口 */ public interface Account { /** * 查询账户 */ void query(); /** * 更新账户 */ void update(); }
- 实现接口方法
public class AccountImpl implements Account { static { System.out.println("初始化操作"); } @Override public void query() { System.out.println("查询账户余额"); } @Override public void update() { System.out.println("更新账户余额"); } }
- 定义一个代理对象(请注意代码中
getAccount()
方法)
public class AccountProxy implements Account { private AccountImpl account; public AccountImpl getAccount() { if (account == null) { this.account = new AccountImpl(); } return account; } @Override public void query() { System.out.println("查询操作预处理"); // 调用真正的查询账户方法 getAccount().query(); System.out.println("查询操作后回调"); } @Override public void update() { System.out.println("更新操作预处理"); // 调用真正的更新账户方法 getAccount().update(); System.out.println("更新操作后回调"); } }
- 调用方法
public class Main { public static void main(String[] args) { AccountProxy accountProxy = new AccountProxy(); accountProxy.query(); accountProxy.update(); } }
动态代理
与静态代理不同,动态代理实在运行时动态生成代理类。不需要像静态代理一样为每一个接口写一个代理方法
或者对象,更方便而且利于维护。
动态代理的实现技术有很多,JDK 自带动态处理,CGLIB 和 ASM 库等也都提供了相关的处理方法。
JDK
- 定义一个接口
public interface TaskService { void complete(); }
- 实现接口方法
public class TaskServiceImpl implements TaskService { static { System.out.println("初始化操作"); } @Override public void complete() { System.out.println("完成任务"); } }
- 代理实现
public class TaskProxy implements InvocationHandler { private Object target; public Object bind(Object target) { this.target = target; //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用 //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result; System.out.println("预处理操作"); result = method.invoke(target, args); System.out.println("回调操作"); return result; } }
- 运行
public class Main { public static void main(String[] args) { TaskServiceImpl taskServiceImpl = new TaskServiceImpl(); TaskProxy proxy = new TaskProxy(); TaskService taskService = (TaskService) proxy.bind(taskServiceImpl); taskService.complete(); } }
CGLIB
由于该种实现是基于 extend 的方式,所以对于 final 类型的方法无法进行代理执行
- 方法定义
public class ProcessService { public void start() { System.out.println("流程启动处理"); } }
- 代理
public class ProcessServiceAgent implements MethodInterceptor { private Object target; public Object getInstance(Object object) { this.target = object; Enhancer enhancer = new Enhancer(); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类) enhancer.setSuperclass(this.target.getClass()); //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦 enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("预处理操作"); methodProxy.invokeSuper(o, objects); System.out.println("回调操作"); return null; } }
- 运行
public class Main { public static void main(String[] args) { ProcessService processService = new ProcessService(); ProcessServiceAgent processServiceAgent = new ProcessServiceAgent(); ProcessService instance = (ProcessService) processServiceAgent.getInstance(processService); instance.start(); } }
其他
常用的应用场景
- 远程代理
- 虚拟代理
- 安全代理
- 指针引用
- 延迟加载
文档参考
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于