Java代理笔记
代理顾名思义,就是一个中间层,当我们要使用某个方法时,不直接调用,而是告诉代理,让代理替我们去请求方法,并返回结果。在这个过程中,我们只知道代理执行并返回给了我们操作结果,至于它有没有其他操作并不知道,但这个也无关紧要,因为不管代理在请求实际方法之前和之后做了什么,对我们都不会产生任何影响。由于代理的这个特性,可以用来进行记录日志等操作。
代理分为静态代理和动态代理。
静态代理
静态代理需要我们在调用者和具体的执行者之间创建一个代理类,其实现需要被代理的接口并持有一个此接口,具体代码如下:
接口类(被代理):
public interface Hello {
void say(String name);
}
代理类:
public class HelloProxy implements Hello {
private Hello helloImpl;
public HelloProxy() {
this.helloImpl = new HelloImpl(); // HelloImpl为一个Hello接口的一个普通实现类
}
@Override
public void say(String name) {
System.out.println("before say");
helloImpl.say(name);
System.out.println("after say");
}
}
使用的时候只需要new一个代理类赋值给接口即可:Hello hello = new HelloProxy(),之后的执行会由代理类去负责。但是这么做有一个问题就是对每个需要代理的类,都需要创建一个对应的代理类,即使代理类的逻辑都是相似的,动态代理就是解决这个问题的。
动态代理
动态代理相当于在调用者和代理类之间又增加了一个中间层,在这个中间层中完成代理类的逻辑,达到复用代码的效果。这个中间层需要实现InvocationHandler接口,并持有一个被代理的类,大致代码如下:
public class Myproxy implements InvocationHandler {
private Object target; // 被代理的类
public Myproxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke"); // 执行代理的方法前进行的操作
Object invoke = method.invoke(target, args); // 调用执行被代理的方法
System.out.println("after invoke"); // 执行代理的方法后进行的操作
return invoke; // 返回方法执行结果
}
}
使用时,使用Proxy的静态方法获取代理类,将其强转为对应的接口,之后可以同静态代理类同样使用。
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
其中loader为类加载器,interfaces为要代理的接口,h为之前定义的实现InvocationHandler接口的类的实例。
这个方法会返回一个代理类,其实现的要代理的接口,并持有一个实现InvocationHandler接口的实例,代理类的代码大致如下:
public final class $Proxy0 extends Proxy
implements Hello
{
public $Proxy0(InvocationHandler paramInvocationHandler) {
super(paramInvocationHandler);
}
public final String say() {
try
{
return ((String)this.h.invoke(this, m3, null));
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
}
如上代码我们可以将其强转为Hello接口,实际调用的时候会调用InvocationHandler实现类中的invoke方法,而其中就是我们实现的代理业务,当然,也包括实际的业务。
这样,对于有相同代理业务的类,我们只要实现InvocationHandler接口,在其中的invoke方法实现需要代理的业务,使用时只要使用Proxy.newProxyInstance静态方法,传入对应得参数即可得到需要的代理类,再将其强转赋值给需要的接口,即可正常使用。
Java代理笔记的更多相关文章
- Java学习笔记——动态代理
所谓动态,也就是说这个东西是可变的,或者说不是一生下来就有的.提到动态就不得不说静态,静态代理,个人觉得是指一个代理在程序中是事先写好的,不能变的,就像上一篇"Java学习笔记——RMI&q ...
- java学习笔记13--反射机制与动态代理
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...
- 瘋耔java语言笔记
一◐ java概述 1.1 ...
- Java系列笔记(2) - Java RTTI和反射机制
目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这 ...
- Java系列笔记(1) - Java 类加载与初始化
目录 类加载器 动态加载 链接 初始化 示例 类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用. 每个类编译后产生一个 ...
- Java学习笔记4
Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...
- 【转载】Java系列笔记(1) - Java 类加载与初始化
Java系列笔记(1) - Java 类加载与初始化 原文地址:http://www.cnblogs.com/zhguang/p/3154584.html 目录 类加载器 动态加载 链接 初始化 示例 ...
- JAVA自学笔记27
JAVA自学笔记27 1.类的加载 1)当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. ①加载:就是指将class文件读入内存,并为之创 ...
- head first java读书笔记
head first java读书笔记 1. 基本信息 页数:689 阅读起止日期:20170104-20170215 2. 标签 Java入门 3. 价值 8分 4. 主题 使用面向对象的思路介绍J ...
随机推荐
- jupyternotebook安装
本篇阅读目录 一.Jupyter notebook环境安装 二.爬虫介绍 回到顶部 一.Jupyter notebook环境安装 1.Anaconda 以及 安装步骤 Anaconda指的是一个开源的 ...
- Python+Android进行TensorFlow开发
Tensorflow是Google开源的一套机器学习框架,支持GPU.CPU.Android等多种计算平台.本文将介绍在Tensorflow在Android上的使用. Android使用Tensorf ...
- scrapydweb的初步使用(管理分布式爬虫)
https://github.com/my8100/files/blob/master/scrapydweb/README_CN.md 一.安装配置 1.请先确保所有主机都已经安装和启动 Scrapy ...
- (转)协议森林13 9527 (DNS协议)
协议森林13 9527 (DNS协议) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在周星驰的电影<唐伯虎点秋香> ...
- EPX-Studio脚本调用
procedure TF408017792.Button1Click(Sender: TObject); var NEPX: IExcelPanelXDisp; begin NEPX := this. ...
- 还记得第一个看到的Flutter组件吗?
注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 MaterialApp 在学习Flutter的过程中我们第 ...
- 洛古 P1312 Mayan游戏(dfs+剪枝)
题目链接 这道题和俄罗斯方块很像 很明显,我们可以看出这是一个dfs,但是,我们需要几条剪枝: 1.如果只剩下1个或2个同样颜色的方块,那么直接退出 2.相同的块不用交换 3.注意优先性,优先左边换右 ...
- Linux软件安装之JDK的安装
JDK的安装 1.1. 下载JDK,此处版本是1.8u131,实际操作以自己具体版本为准 先查看Linux系统是多少位(32位/64位):getconf LONG_BIT 然后去官网下载JDK [jd ...
- Dubbo 扩展点加载机制:从 Java SPI 到 Dubbo SPI
SPI 全称为 Service Provider Interface,是一种服务发现机制.当程序运行调用接口时,会根据配置文件或默认规则信息加载对应的实现类.所以在程序中并没有直接指定使用接口的哪个实 ...
- Mac brew命令的使用
mac 终端程序管理工具 能让你更快速的安装你想要的工具.而不用考虑大量的依赖. 安装brew复制下面的命令,终端执行 官网Homebrew /usr/bin/ruby -e "$(cur ...