第 1 章 Java动态代理介绍
1.1、动态代理介绍
Java动态代理是在运行时期动态生成代理对象的技术,通过代理对象可以在不改变原始代码的情况下,执行原始类的方法前后自定义的逻辑,对原始类方法的功能进行增强或拦截。
1.2、动态代理技术的应用场景
1、AOP编程:通过动态代理实现AOP编程,可以在不改变原有代码的情况下,实现对程序的横向扩展,比如日志记录、事务处理等。
2、RPC框架:通过动态代理可以实现远程方法调用,比如Dubbo、Spring Cloud等。
3、数据库连接池:通过动态代理可以实现数据库连接的池化,实现资源的重复利用,提高程序的性能。
4、消息中间件:通过动态代理可以实现消息的异步处理,比如Kafka、RocketMQ等。
5、权限控制:通过动态代理可以实现权限控制,比如在方法调用前进行权限校验,只有拥有权限的用户才能执行该方法。
6、缓存代理:通过动态代理可以实现缓存代理,将方法的返回值缓存起来,下次调用时可以直接返回缓存中的值,避免重复计算。
7、性能监控:通过动态代理可以实现性能监控,比如统计方法的执行时间、调用次数等信息,方便分析程序的性能瓶颈。
第 2 章 Java动态代理编码实现
代码在文档的最后~~~
2.1、简单动态代理编码实现
执行结果:
2.2、动态代理性能监控编码实现
需求背景:某系统有一个用户管理类,包含用户登录,删除用户,查询用户等功能,系统要求不修改原有代码的情况下统计每个功能的执行耗时情况,以便后期观察程序性能。
1、用户管理类代码
2、使用动态代理实现性能监控
3、程序执行结果
往期回顾
(37条消息) Postman接口测试项目实战_接口测试实战_春天播种秋天收获的博客-优快云博客
(37条消息) Oracle数据库和PLSQL可视化工具学习笔记_plsql工具介绍_春天播种秋天收获的博客-优快云博客
(37条消息) Python+Selenium自动化测试项目实战_selenium自动化测试实战基于python_春天播种秋天收获的博客-优快云博客
代码:
一、Cat代理业务
package net.yxclass.cat; //1、定义接口 public interface Cat { void eat(); }
package net.yxclass.cat; //2、定义代理目标对象 public class LazyCatImpl implements Cat { @Override public void eat() { System.out.println("如果不把饭放到嘴边就不吃饭啦~~~"); } }
package net.yxclass.cat; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //3、定义一个代理类,该代理类实现InvocationHandler接口,重写invoke方法。 public class CatProxy implements InvocationHandler { private Object target; public CatProxy(Object target) { this.target = target; } public static void preconditions() { System.out.println("把饭送到LazyCat的嘴边~~~"); } public static void postWork() { System.out.println("LazyCat吃完饭后为他收拾餐具~~~"); } //invoke方法,参数1:为代理的目标对象;参数2:代理目标对象的方法;参数3:代理目标对象方法的形参列表 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在调用LazyCat吃饭方法前先调用代理对象把饭送到他的嘴边~~~ preconditions(); //LazyCat吃饭的方法 Object invoke = method.invoke(target, args); //LazyCat吃完饭后为他收拾餐具~~~ postWork(); return invoke; } }
package net.yxclass.cat; import java.lang.reflect.Proxy; //4、创建启动类 public class ProxyApp { public static void main(String[] args) { //创建代理的目标对象 Cat cat = new LazyCatImpl(); //创建InvocationHandler对象 CatProxy catProxy = new CatProxy(cat); //创建代理对象 Cat proxy = (Cat) Proxy.newProxyInstance( cat.getClass().getClassLoader(),// 获取原始对象的类加载器 cat.getClass().getInterfaces(),// 获取原始对象实现的接口列表 catProxy);// 传入代理对象的InvocationHandler对象 //调用代理对象的方法 proxy.eat(); } }
二、性能监控代理业务
package net.yxclass.admin; // 用户业务接口 public interface UserService { // 登录功能 void login(String loginName,String passWord) throws Exception; // 删除用户 void deleteUsers() throws Exception; // 查询用户,返回数组的形式。 String[] selectUsers() throws Exception; }
package net.yxclass.admin; // 用户业务实现类(面向接口编程) public class UserServiceImpl implements UserService{ @Override public void login(String loginName, String passWord) throws Exception { if("admin".equals(loginName) && "123456".equals(passWord)){ System.out.println("您登录成功,欢迎光临本系统~"); }else { System.out.println("您登录失败,用户名或密码错误~"); } Thread.sleep(1000); } @Override public void deleteUsers() throws Exception{ System.out.println("成功删除了1万个用户~"); Thread.sleep(1500); } @Override public String[] selectUsers() throws Exception{ System.out.println("查询出了3个用户"); String[] names = {"令狐冲", "郭靖", "杨过"}; Thread.sleep(500); return names; } }
package net.yxclass.admin; import java.lang.reflect.Proxy; import java.time.Duration; import java.time.Instant; import java.util.Arrays; public class LoginApp { public static void main(String[] args) throws Exception { // 需求:为UserServiceImpl类创建一个代理对象---让代理对象来测试程序的性能 // 创建UserServiceImpl的对象 UserServiceImpl userService = new UserServiceImpl(); // 获取类加载器 ClassLoader classLoader = userService.getClass().getClassLoader(); // 指定接口 Class[] interfaces = {UserService.class}; // 调用Proxy的newProxyInstance方法为userService创建一个代理对象,InvocationHandler是单函数式接口,所以使用Lambda表达式来写 UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, (proxy1, method, args1) -> { // 只要代理对象调用方法就会来到这里执行 // 在这里指定代理要做的事情 if (method.getName().equals("login") || method.getName().equals("deleteUsers") || method.getName().equals("selectUsers")) { // 记录方法调用前的时间 Instant now1 = Instant.now(); // 执行被代理对象的login方法 Object res = method.invoke(userService, args1); // 记录方法执行完成后的时间 Instant now2 = Instant.now(); //计算方法执行时长 Duration betweenTime = Duration.between(now1, now2); System.out.println(method.getName() + "方法耗时:" + betweenTime); return res; } Object res = method.invoke(userService, args1); return res; }); // 吩咐代理做事情 proxy.login("admin", "123456"); System.out.println("---------------"); proxy.deleteUsers(); System.out.println("----------------"); String[] users = proxy.selectUsers(); System.out.println("users: " + Arrays.toString(users)); System.out.println("----------------"); // 不需要代理做其他事情,只需要代理叫被代理对象来执行toString方法 String res = proxy.toString(); System.out.println("res = " + res); } }