中流砥柱java的动态代理
时间:2022-07-23
本文章向大家介绍中流砥柱java的动态代理,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
背景
在我们学习Spring框架的时候我们是否思考过,Spring是如何实现bean实列注入到IOC容器中呢?我们如何去
权威指南
代理是基本的设计模式之一,他是为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色。 Java的动态代理比代理的思想更迈进了一步,因为他可以动态地创建代理并动态的处理对所代理的方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,他的工作是揭示调用的类型并确定相应的对策。 -------《ThinKing in Java》
个人理解
- 类比生活 代理,平时生活中代理无处不在,如手机生产商的代理商A,A不仅能帮忙给生产商卖手机而且也提供了售后功能。代码中被代理对象就是生产商,而代理商A就是代理对象,可以做生产商的事情,为了方便客户还提供了售后的功能。但是此时这个生产商不固定,且随时会变,且为了利益最大化,那个生产商拿货便宜,就拿谁的货,就在这个时候我们是不是就得成为一个动态代理商?这样就可以方便用户,还能和生产商解耦合。
- 抽象层面 将一个对象被另一个对象代理,代理对象可以扩展被代理对象的方法,且能在被代理对象对象增加方法。这样实现好之后我们所代理的对象会在编译和累加载之后将带代理对象和被代理对象绑定到一块了。为了让代理更加方便和实用于是就得出了动态代理,也就是再程序运行时可以根据被代理对象生成代理对象。(在java中反射机制就是可以让代码进行动态加载和生成对象)
jdk动态代理
- JDK的动态代理也就是基于Java的反射机制实现的。
- 我们先来看一下Java中的动态代理在代码中是如何实现的:
package dynamicproxy;
import java.lang.reflect.*;
/**
* @Author:yuanxindong
* @Date:2020/5/90:53
*/
public class Client {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//实例化一个对象
//分别分为两种方事实现的,一个是直接new 关键字创建一个对象,
// 第二种是通过反射机制穿件一个对象
//UserServiceImpl userServiceLmpl = new UserServiceImpl();
//1。 读取加载"dynamicproxy.UserServiceImpl"路径下的class对象
Class aClass = Class.forName("dynamicproxy.UserServiceImpl");
//使用class对象中的方法获取父类加载器
//ClassLoader classLoader = userServiceLmpl.getClass().getClassLoader();
ClassLoader classLoader = aClass.getClassLoader();
//Class [] interfaces = userServiceLmpl.getClass().getInterfaces();
//获取实现class实现的接口
Class[] interfaces = aClass.getInterfaces();
//获取这个类的、构造方法
Constructor constructors = aClass.getConstructor();
//通过构造方法 去实例化这个对象
UserServiceImpl userServiceLmpl = (UserServiceImpl) constructors.newInstance();
//将获取到的对象传入对应的处理器上,通过反射的方式拿到对应的方法切织入
InvocationHandler logHandler = new LogHandler(userServiceLmpl);
//创建动态代理对象的接口
UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, logHandler);
proxy.select();
proxy.update();
ProxyUtils.generateClassFile(userServiceLmpl.getClass(), "UserServiceProxy");
}
}
被代理的对象
/**
* @Author:yuanxindong
* @Date:2020/5/90:56
*/
public interface UserService {
public void select();
public void update();
}
package dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @Author:yuanxindong
* @Date:2020/5/90:47
*/
public class LogHandler implements InvocationHandler {
private Object target;
//使用构造方法将代理对象传入代理对象
public LogHandler(Object target){
this.target = target;
}
//通过反射的方式执行并织入(不知道用的是否合理)代理方法,这个接口实现方法会被newProxyInstance()方法使用
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
//
Object result = method.invoke(target,args);
after();
return result;
}
private void before(){
System.out.println("log start"+ System.currentTimeMillis());
}
private void after(){
System.out.println("log end" + System.currentTimeMillis());
}
}
执行结果:
demo中的InvocationHandler
- 从demo中看我们将代理对象的其他方法是在实现InvocationHandler的类中写的,通过实现的invoke()方法将被代理类织入代理类的方法中 然后在newProxyInstance()方法中实例化这个 invoke()方法成为代理对象。如下面的源码所示:
总结
jdk的动态代理通过Java反射机制实现 主要的方法是:
- 实现被代理的方法:继承InvocationHandler接口 实现其invoke方法
InvocationHandler logHandler = new LogHandler(userServiceLmpl);
- 使用Proxy.newProxyInstance(classLoader, interfaces, logHandler),创建代理对象。
UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, logHandler);
思考
- Spring AOP是怎样实现的呢?? 也是像我们上面的方法那样织入的吗???
- explain 深入剖析 MySQL 索引及其性能优化指南
- 图文并茂详解 SQL JOIN
- 自定义 hadoop MapReduce InputFormat 切分输入文件
- Hadoop MapReduce 二次排序原理及其应用
- MySQL Tips【Updating】
- Meltdown、Spectre攻击---CPU乱序执行和预测执行导致的安全问题
- WordPress 4.6远程代码执行漏洞(CVE-2016-10033)复现环境搭建指南
- 相似文档查找算法之 simHash 简介及其 java 实现
- Hadoop 中利用 mapreduce 读写 mysql 数据
- Android O中对TEE加解密算法的新要求
- storm 原理简介及单机版安装指南
- Python Tips, Tricks, and Hacks
- 英特尔放出Linux微代码以修复Meltdown和Spectre漏洞
- python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Java File类基础解析 使用递归来遍历目录 2
- Java Lambda表达式
- 介绍一款 API 敏捷开发工具
- XSS(跨站脚本攻击)简单讲解
- Java中多线程的使用(超级超级详细)线程池 7
- Python 将土味情话语录设置为桌面壁纸
- Java中多线程的使用(超级超级详细)线程安全原理解析 4
- Java中多线程的使用(超级超级详细) Thead类的使用 3
- Java Properties集合基础解析
- File 类基础解析3 文件过滤器优化
- 原创 | 我在git merge的时候遇到了冲突,怎么解决?
- protobuffer的前世今生(一)——简介
- protobuffer的前世今生(二)——编码
- Java中多线程的使用(超级超级详细)+多线程的实现原理 2
- protobuffer的前世今生(三)——序列化和反序列化性能比较