投票动态代理proxy案例(java)
一、动态代理相关知识贮备:
1、代理类在程序运行时创建的代理方式被称为动态代理
2、动态代理相对于静态代理的优势在于代码的通用性,可以很方便地完成对代理类中函数的统一处理。充分的代码复用,提高开发效率,凝练了代码结构。
3、代理的意思通俗地讲,就是代理类帮助被代理类执行操作,同时在代理类中过滤掉部分不合规定的操作。举个例子,一些人要做类似的事情,比如班上同学都要交资料费给学校,班上的系列同学相当于被代理对象,班长相当于代理对象,班上同学交资料费的操作通过班长的协助完成,表面上是代理对象的班长交资料费,实际上是班长对象的交资料费方法中调用了班上同学对象的交资料费方法,班长起到的是转交作用。这样做的好处是在班长这里可以做一个过滤,比如资料费不能重复交,在班长这里记录已交费名单,如果重复交会通过业务逻辑判断检查出来,因重复而交资料费失败。还有如果资料费需要分类交,也可以在班长这一代理层对分类逻辑进行一定处理,即有的同学可能没修某门课有的修了,大家都是用的交费统一接口,班长这里就可以做分类判断,将数据给分流归类好。班长作为中间的代理,可以统一处理下级部分不合理操作,减轻了上级对象的负担。
二、题目要求:
1.现有一个投票管理器的接口VoteManagerInterface ,该接口用来管理学生选举班长等活动。
public interface VoteManagerInterface {
void addStudent(Student s);
boolean vote(Student voter,Student select);
int getVoteNum(Student s);
}
接口中 :
(1)addStudent(Student s) 方法用来添加学生候选人;
(2)boolean vote(Student voter,Student select) 方法用来提交 学生voter 投了 学生select 一票,返回值表示是否投票成功;
(3)int getVoteNum(Student s) 方法用来获取某个学生的得票数。
2.VoteManager类是接口的一个实现,
3.要求实现VoteManager的代理类,控制对VoteManager的访问(每个学生不能多次投其他某学生的票,且学生不能投自己)。
三、UML类图:
四、运行代码:
1、Student信息类:
import java.util.ArrayList;/*** @author:tengsen* @create: 2022-10-06 20:42* @Description: Student信息类*/
public class Student {private String id;private String name;private int age;//记录被投了多少票private int numberOfVotes;//记录有哪些人投过这个同学(记录名字)private ArrayList<String> voters;public Student() {}public Student(String id, String name, int age) {this.id = id;this.name = name;this.age = age;numberOfVotes = 0;voters = new ArrayList<>();}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public int getNumberOfVotes() {return numberOfVotes;}public void setNumberOfVotes(int numberOfVotes) {this.numberOfVotes = numberOfVotes;}public ArrayList<String> getVoters() {return voters;}public void setVoters(ArrayList<String> voters) {this.voters = voters;}
}
2、投票管理接口:
/*** @Author: tengsen* @Description: 投票管理接口* @Date: 2022/10/6*/
public interface VoteManagerInterface {//添加学生候选人void addStudent(Student s);//提交投票,学生voter投了学生select 一票,返回值表示是否投票成功boolean vote(Student voter, Student select);//获取某个学生的得票数int getVoteNumbers(Student s);
}
3、投票管理类:
import java.util.ArrayList;
import java.util.List;/*** @author:tengsen* @create: 2022-10-06 20:42* @Description: 投票管理类,实现了投票管理接口*/
public class VoteManager implements VoteManagerInterface {//该集合管理候选人,记录候选人有哪些(存学生对象)private List<Student> students = new ArrayList<>();@Overridepublic void addStudent(Student s) {//下标大于等于0,相当于该候选人已经存在,不能重复添加if(students.indexOf(s)>=0){System.out.println(s.getName()+"已经成为候选人,不可以再次添加");}else {students.add(s);System.out.println("成功添加"+s.getName()+"为候选人");}}@Overridepublic boolean vote(Student voter, Student select) {int index = students.indexOf(select);//更改候选人的票数students.get(index).setNumberOfVotes(students.get(index).getNumberOfVotes()+1);//更改支持候选人的投票者名单students.get(index).getVoters().add(voter.getName());System.out.println(voter.getName()+"给"+select.getName()+"投票成功");return true;}@Overridepublic int getVoteNumbers(Student s) {int index = students.indexOf(s);//查找的index为负数,相当于传进来的s不在候选人集合中,票数为0if(index<0){System.out.println(s.getName()+"不是候选人,所有没有票数");return 0;}return students.get(index).getNumberOfVotes();}
}
4、实现InvocationHandler接口的代理类:
代理类实现接口,调用处理程序,此处使用的是java已经封装好的工具
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** @author:tengsen* @create: 2022-10-08 08:33* @Description: 代理类实现接口,调用处理程序,此处使用的是java已经封装好的工具(java.lang.reflect.InvocationHandler)*/
public class MyInvocationHandler implements InvocationHandler {private Object obj;//通过构造器注入被代理的对象public MyInvocationHandler(Object obj) {this.obj = obj;}//参数proxy代表生成的代理对象,参数method是被代理对象对应的执行方法的抽象,参数args是被代理方法中的参数数组。@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object rtValue = null;//method.getName拿到当前执行方法的方法名if ("vote".equals(method.getName())) {Student voter = (Student) args[0];Student select = (Student) args[1];//投票者和候选者名字相同,不能给自己投票if (voter.getName().equals(select.getName())) {System.out.println(voter.getName() + "不能自己给自己投票");return false;}//在候选人的已支持者名单中找到当前投票人名字,说明当前投票人已经投过该候选人了for (String s : select.getVoters()) {if (s.equals(voter.getName())) {System.out.println(voter.getName() + "已经给" + select.getName() + "投过票了,不能重复投");return false;}}}//调用InvocationHandler的invoke方法,相当于执行被代理对象当前需要执行的方法rtValue = method.invoke(obj, args);return rtValue;}
}
5、投票测试类:
import java.lang.reflect.Proxy;/*** @author:tengsen* @create: 2022-10-06 20:42* @Description: 动态代理投票测试类*/
public class VoteTest {public static void main(String[] args) {//创建投票管理类实例VoteManager voteManager = new VoteManager();//创建实现InvocationHandler接口的代理类实例MyInvocationHandler myInvocationHandler = new MyInvocationHandler(voteManager);//创建代理对象实例(调用Proxy类的newProxyInstance方法)//newProxyInstance的参数格式:
// public static Object newProxyInstance(ClassLoader loader,
// Class<?>[] interfaces,
// InvocationHandler invocationHandler)//参数load:是一个ClassLoader对象,传入被代理类的类加载器,该加载器同时也是代理的加载器//参数interfaces:是一个interface对象数组,表示被代理对象相关的接口。如果我们提供了这样一个接口对象数组,也就是声明了代理类实现了这些接口,代理类就可以使用这些接口中声明的方法。//参数invocationHandler:表示的是当前动态代理对象调用执行方法时会关联到哪一个InvocationHandler对象上VoteManagerInterface voteManagerProxy = (VoteManagerInterface) Proxy.newProxyInstance(VoteManagerInterface.class.getClassLoader(),new Class<?>[]{VoteManagerInterface.class},myInvocationHandler);//创建学生实例Student s1 = new Student("001","柳一",18);Student s2 = new Student("002","关二",19);Student s3 = new Student("003","张三",20);Student v1 = new Student("004","李四",21);Student v2 = new Student("005","王五",19);Student v3 = new Student("006","赵六",20);//将候选人实例添加投票管理代理实例中voteManagerProxy.addStudent(s1);voteManagerProxy.addStudent(s2);voteManagerProxy.addStudent(s3);//重复添加候选人(失败案例)voteManagerProxy.addStudent(s2);//通过投票管理代理投票(投票人给候选人投)voteManagerProxy.vote(v1,s1);voteManagerProxy.vote(v2,s1);voteManagerProxy.vote(v3,s1);//v1重复给s1投票(失败案例)voteManagerProxy.vote(v1,s1);//通过投票管理代理投票(投票人给候选人投)voteManagerProxy.vote(v1,s2);voteManagerProxy.vote(v2,s2);voteManagerProxy.vote(v3,s3);//通过投票管理代理获取某一候选人的当前票数System.out.println(s1.getName()+"的票数是"+voteManagerProxy.getVoteNumbers(s1));System.out.println(s2.getName()+"的票数是"+voteManagerProxy.getVoteNumbers(s2));System.out.println(s3.getName()+"的票数是"+voteManagerProxy.getVoteNumbers(s3));//v1不是候选人,没有票数,返回0票System.out.println(v1.getName()+"的票数是"+voteManagerProxy.getVoteNumbers(v1));}
}
五、运行结果:
投票动态代理proxy案例(java)相关推荐
- 【java】深入分析Java反射-动态代理 proxy
1.概述 转载:深入分析Java反射(四)-动态代理 [Java]Java 反射机制浅析 [Java]java代理 静态代理 动态代理 proxy [java]静态代理 proxy 2.动态代理的简介 ...
- 动态代理proxy与CGLib的区别
转载自 动态代理proxy与CGLib的区别 昨天被人问及动态代理与CGlib的区别,赶紧回顾一下: 什么是代理? 静态代理与动态代理 静态代理实例 JDK动态代理实例 CGLib 简介 CGLib ...
- 【Java】java代理 静态代理 动态代理 proxy
文章目录 1.为什么要用代理 1.静态代理 2.动态代理 2.1. 什么叫代理? 2. 2. 什么叫动态代理? 2. 3. 动态代理有什么优势? 2. 4. 什么情况下使用代理? 2.5 jdk动态代 ...
- jdk动态代理proxy
目录 jdk和cglib区别 以下案例: 定义共同行为接口 被代理类(目标类) jdk动态代理类-动态生成代理类和被代理方法的调用 解析动态生成的代理类$Proxy0.class 静态代理需要自己实现 ...
- SSM3==理解静态代理、动态代理Proxy.newProxyInstance、cglib代理==通过纯XML配置spring AOP,通过纯注解配置spring AOP
静态代理: 为什么要代理?在不改动原代码的基础上,丰富调用某个方法时实现的功能. 比如service类中原本update只会更新,但是通过代理类加上了判断权限和输出时间的功能. 其实这些功能也可以写在 ...
- 动态代理/spring IOC/JAVA反射机制
动态代理 代理的作用就是控制对象的访问权限: 首先我们需要写一个接口 这个就是代理接口 public interface Student { public void S1(); } 然后在写一个接口的 ...
- spring18-1:采用jdk的动态代理 proxy。
接口 public interface UserService {void addUser();void updateUser(); } 接口的实现类 public class UserService ...
- 【VirtualAPP 双开系列03】动态代理-hook系统服务(Java层)
目录: 1. Hook 简述 2. VirtualAPP Java Hook 类图 3. VirtualAPP Java Hook 实例 (ActivityManagerService) 1. Hoo ...
- Java动态代理代码案例:使用jdk自带的Proxy只能对有接口的类进行动态代理
- Java动态代理代码案例:使用cglib实现对无接口的类进行动态代理
最新文章
- 首次看清体内所有癌症转移灶,深度学习方法立大功!中国留学生一作论文登《细胞》封面...
- php think命令用不了,自定义 PHP think 命令无法在命令类文件里面使用 Db 类
- Js弹性漂浮广告代码
- php中使用exec,system等函数调用系统命令
- bzoj1791,P4381-[IOI2008]Island【基环树,树形dp,单调队列dp,树的直径】
- python字符串排序_Python对字符串列表进行排序
- linux 25端口漏洞,一封突如其来的邮件443端口漏洞
- 基于uFUN开发板的RGB调色板
- Erros while compiiing.Reload prevented
- 腾讯云服务器Lighthouse和CVM区别
- gtp怎么安装系统_gpt格式硬盘如何安装win7系统教程
- 腾讯视频Node.js服务是如何支撑国庆阅兵直播高并发的?
- js:聚焦和失焦事件示例
- NVIDIA 显卡驱动CUDA ToolkitcuDNN下载地址
- python datetime计算时间差_python计算时间差的方法
- 将笔记本打造成遥控器――远程桌面控制台式机
- Python神器!只需一行代码,纯文本秒变Markdown!
- Fedora 服务启动管理
- GAE 博客——B3log Solo 0.2.1 发布了!
- 用Matlab求拐点和凹凸区间需要使用MATLAB