网站首页 > java教程 正文
代理(Proxy)的概念很好理解,就是在我们使用某个类A(被代理对象)的时候,不是直接使用该类A本身,而是通过新建一个类B(代理类),在类B中调用类A,从而可以实现通过使用类B来达到使用类A的目的。同时我们可以在类B中对类A的功能进行扩展。这样就可以在不改动类A的前提之下,加入我们新的功能需求,可以实现增强类A的功能。
举个例子,假设现在有一个类A:
class A{
public void method1(String p) {
System.out.print("Hello ");
System.out.println(p);
}
private void method2(String p) {
System.out.print("Hello ");
System.out.println(p);
}
}
不使用代理的时候我们直接调用类A的method1:
public static void main(String[] args) {
A a = new A();
a.method1("Java");
}
假设现在有个需求,要求打印出类A中method1的入参和该方法执行的开始和结束时间,但是不能修改类A。我们可以用下面两种方式实现:
第一种,我们创建一个类B,在类B中注入一个类A的对象a,同时编写一个和类A.method1同样结构的方法,并在这个方法中调用a.method1(),代码如下:
class B{
private A a;
public B(A a) {
this.a = a;
}
public void method1(String p) {
System.out.println("request param : " + p);
System.out.println("method start at " + new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS").format(new Date()));
a.method1(p);
System.out.println("method end at " + new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS").format(new Date()));
}
}
然后我们可以这么调用:
public static void main(String[] args) {
B b = new B(new A());
b.method1("Java");
}
这种实现方式需要满足两个条件:
- 类A不能是抽象类
- method1必须是public的
第二种,我们可以创建一个类B来继承类A,然后重写类A的method1,代码如下:
class B extends A{
@Override
public void method1(String p) {
System.out.println("request param : " + p);
System.out.println("method start at " + new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS").format(new Date()));
super.method1(p);
System.out.println("method end at " + new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS").format(new Date()));
}
}
然后我们可以这么调用:
public static void main(String[] args) {
B b = new B();
b.method1("Java");
}
这种实现方式需要满足条件:
- 类A不能是final的
- 类A中的method1 必须是public的,并且不能是final的
第三种,如果类A是实现了IA接口的,并且方法method1是重写的方法,那么我们可以创建一个类B也实现接口IA,然后注入类A,代码如下:
interface IA {
void method1(String p);
}
class A implements IA {
@Override
public void method1(String p) {
System.out.print("Hello ");
System.out.println(p);
}
private void method2(String p) {
System.out.print("Hello ");
System.out.println(p);
}
}
class B implements IA {
private A a;
public B(A a) {
this.a = a;
}
@Override
public void method1(String p) {
System.out.println("request param : " + p);
System.out.println("method start at " + new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS").format(new Date()));
a.method1(p);
System.out.println("method end at " + new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS").format(new Date()));
}
}
调用方法同第一种方法。
这种方案跟第一种很相似,抽象出接口好处是可以提前约定好method1的特征,防止在B类中写的代理方法和A类的方法有出入。
这种方式需要满足条件:
- 类A(被代理类)和类B(代理类)都必须实现同一个接口
- 类B只能代理类A中实现接口的那些方法
以上三种方法都可以在不修改类A的基础上对类A的方法进行扩充,满足了开闭原则。
但是以上各种写法你都必须把类B一起编译打包,程序才能正常运行,这样的代理方式称之为静态代理,他的本质就是通过新增一个代理类来对被代理类的方法进行一个拦截,从而可以在调用被代理方法的前后增加我们自己需要的功能。
那么问题来了,大家可以看到上面的做法你必须手动写一个代理类,这样会导致应用的时候我们要编写很多的代理类,而我们实际使用中,很多的增强功能都是一些公共的处理,比如对接口的信息的打印、对一些异常进行统一的封装、对一些事务处理的统一管理等。如果我们使用上面的方式进行,就需要写无数个代理类。这显然不是我们想要的结果。
那么我们继续思考一下,如果可以在程序运行期间,根据我们的需要动态的构建一个代理类,然后执行完代理操作以后就释放掉,这样是不是就可以避免上述问题!这就是动态代理。
下一章中我们介绍动态代理的实现方式及应用场景。
猜你喜欢
- 2024-10-04 java:jdk动态代理(jdk动态代理实现aop)
- 2024-10-04 Java三种代理模式:静态代理、动态代理和cglib代理
- 2024-10-04 Java 学习笔记--反射与代理机制(静态、动态)
- 2024-10-04 Java的动态代理如何实现?#程序员(java动态代理有什么用)
- 2024-10-04 Java动态代理与静态代理以及它能为我们做什么
- 2024-10-04 Java - 动态代理实现原理以及ASM技术
- 2024-10-04 深入理解Java反射和动态代理(jdk动态代理和反射)
- 2024-10-04 java手把手教你写动态代理和静态代理的实现
- 2024-10-04 Java动态代理简单介绍(java动态代理的两种方式)
- 2024-10-04 Java核心技术点之动态代理(java动态代理实现三种方式)
你 发表评论:
欢迎- 06-15Linux中如何通过Shell脚本来控制Spring Boot的Jar包启停服务?
- 06-15推荐一款超棒的SpringCloud 脚手架项目
- 06-15IDEA将项目打包成jar包(idea打包普通java项目)
- 06-15Spring Boot3 项目 jar 包打包成 Docker 镜像全攻略
- 06-15记录Dockerfile将jar包构建成部署所需的镜像
- 06-15项目基础部署汇总八---linux下xxl-job安装
- 06-15Spring Boot Jar 包秒变 Docker 镜像实现多环境部署
- 06-15终端执行 java -jar example.jar 时报错:“没有主清单属性” 的解决
- 最近发表
-
- Linux中如何通过Shell脚本来控制Spring Boot的Jar包启停服务?
- 推荐一款超棒的SpringCloud 脚手架项目
- IDEA将项目打包成jar包(idea打包普通java项目)
- Spring Boot3 项目 jar 包打包成 Docker 镜像全攻略
- 记录Dockerfile将jar包构建成部署所需的镜像
- 项目基础部署汇总八---linux下xxl-job安装
- Spring Boot Jar 包秒变 Docker 镜像实现多环境部署
- 终端执行 java -jar example.jar 时报错:“没有主清单属性” 的解决
- 如何将本地JAR文件添加到Maven项目中
- Java 类隔离应用:多 Jar 包支持(java接口隔离原则)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)