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的访问(每个学生不能多次投其他某学生的票,且学生不能投自己)。
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 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 getVoters() {
return voters;
}
public void setVoters(ArrayList voters) {
this.voters = voters;
}
}
/**
* @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);
}
import java.util.ArrayList;
import java.util.List;
/**
* @author:tengsen
* @create: 2022-10-06 20:42
* @Description: 投票管理类,实现了投票管理接口
*/
public class VoteManager implements VoteManagerInterface {
//该集合管理候选人,记录候选人有哪些(存学生对象)
private List students = new ArrayList<>();
@Override
public void addStudent(Student s) {
//下标大于等于0,相当于该候选人已经存在,不能重复添加
if(students.indexOf(s)>=0){
System.out.println(s.getName()+"已经成为候选人,不可以再次添加");
}else {
students.add(s);
System.out.println("成功添加"+s.getName()+"为候选人");
}
}
@Override
public 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;
}
@Override
public int getVoteNumbers(Student s) {
int index = students.indexOf(s);
//查找的index为负数,相当于传进来的s不在候选人集合中,票数为0
if(index<0){
System.out.println(s.getName()+"不是候选人,所有没有票数");
return 0;
}
return students.get(index).getNumberOfVotes();
}
}
代理类实现接口,调用处理程序,此处使用的是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是被代理方法中的参数数组。
@Override
public 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;
}
}
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));
}
}