今天看面经看到了这里,上网找了些资料,没太看懂,就照着资料上的代码自己动手写了点,这里记录一下我的学习过程。
java动态代理实现与原理详细分析 - Gonjian - 博客园
java动态代理实现_luu_一只程序猿的博客-优快云博客_java动态代理
我主要就是照着这两个写的。
之后的内容有极大可能出错(因为是我个人的感悟),欢迎指正。
首先是静态代理的一点内容
先是一个接口
public interface Person {
//上交班费
void giveMoney();
}
然后是实现类
public class Student implements Person{
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void giveMoney() {
System.out.println(name + "上交班费50元");
}
}
实现类的代理类
public class StudentsProxy implements Person{
//被代理的学生
Student stu;
public StudentsProxy(Person stu) {
// 只代理学生对象
if(stu.getClass() == Student.class) {
this.stu = (Student)stu;
}
}
//代理上交班费,调用被代理学生的上交班费行为
public void giveMoney() {
System.out.println("我帮你交钱吧");
stu.giveMoney();
}
}
测试的代码
//被代理的学生张三,他的班费上交有代理对象monitor(班长)完成
Person zhangsan = new Student("张三");
//生成代理对象,并将张三传给代理对象
Person monitor = new StudentsProxy(zhangsan);
zhangsan.giveMoney();
//班长代理上交班费
monitor.giveMoney();
System.out.println("---------------------------------------------------");
结果
张三上交班费50元
我帮你交钱吧
张三上交班费50元
静态代理就这么结束了。很简单。
然后是动态代理的一部分
动态代理的实现类(或者叫代理类?)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class StuInvocationHandler <T> implements InvocationHandler {
//invocationHandler持有的被代理对象
T target;
public StuInvocationHandler(T target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" +method.getName() + "方法");
Object result = method.invoke(target, args);
return result;
}
}
测试代码(这里用的是比较繁琐的那一套,不建议使用,我的idea里面getProxyClass这个方法加了横线,应该是属于过时的方法)
InvocationHandler stuHandler2 = new StuInvocationHandler<Person>(zhangsan);
Class<?> stuProxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class<?>[] {Person.class});
Constructor<?> constructor = stuProxyClass.getConstructor(InvocationHandler.class);
Person stuProxy2 = (Person) constructor.newInstance(stuHandler2);
stuProxy2.giveMoney();
结果
代理执行giveMoney方法
张三上交班费50元
这样看其实动态代理并没有什么很大的改进,不过我后来意识到,静态代理的话需要每一个类写一个代理类,动态代理有一个就够了。
我又写了个Person 的实现类
public class poorStudent implements Person{
private String name;
public poorStudent(String name) {
this.name = name;
}
@Override
public void giveMoney() {
System.out.println(name + "上交班费5元");
}
}
静态代理的话就需要针对这个类再写一个代理类,动态代理不用
以下是测试代码
poorStudent lisi=new poorStudent("李四");
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler stuHandler = new StuInvocationHandler<Person>(lisi);
//创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
//代理执行上交班费的方法
stuProxy.giveMoney();
System.out.println("---------------------------------------------------");
结果
代理执行giveMoney方法
李四上交班费5元
总的测试代码
//被代理的学生张三,他的班费上交有代理对象monitor(班长)完成
Person zhangsan = new Student("张三");
//生成代理对象,并将张三传给代理对象
Person monitor = new StudentsProxy(zhangsan);
zhangsan.giveMoney();
//班长代理上交班费
monitor.giveMoney();
System.out.println("---------------------------------------------------");
//---------------------------------------------------
poorStudent lisi=new poorStudent("李四");
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler stuHandler = new StuInvocationHandler<Person>(lisi);
//创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
//代理执行上交班费的方法
stuProxy.giveMoney();
System.out.println("---------------------------------------------------");
//---------------------------------------------------
InvocationHandler stuHandler2 = new StuInvocationHandler<Person>(zhangsan);
Class<?> stuProxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class<?>[] {Person.class});
Constructor<?> constructor = stuProxyClass.getConstructor(InvocationHandler.class);
Person stuProxy2 = (Person) constructor.newInstance(stuHandler2);
stuProxy2.giveMoney();
结果
张三上交班费50元
我帮你交钱吧
张三上交班费50元
---------------------------------------------------
代理执行giveMoney方法
李四上交班费5元
---------------------------------------------------
代理执行giveMoney方法
张三上交班费50元
在有很多类要代理的时候,动态代理可以少写很多代码
(代码复用率更高?好像是这么说的)
我又测试了换个接口的实现类
接口和实现类
public interface Teacher {
//收到班费
void getMoney();
}
public class headmaster implements Teacher{
private String name;
public headmaster(String name) {
this.name = name;
}
@Override
public void getMoney() {
System.out.println(name + "领取班费55元");
}
}
测试代码
headmaster wangwu=new headmaster("王五");
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler teaHandler = new StuInvocationHandler<Teacher>(wangwu);
//创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Teacher teaProxy = (Teacher) Proxy.newProxyInstance(Teacher.class.getClassLoader(), new Class<?>[]{Teacher.class}, teaHandler);
//代理执行上交班费的方法
teaProxy.getMoney();
结果
代理执行getMoney方法
王五领取班费55元
可以看出,不光是同一个接口的不同实现类,不同接口的实现类也可以用同一个代理类来进行动态代理(好绕口……),如果是静态代理的话就需要创建多个代理类才行。
就到这里(有相当部分部分代码是人家的,不过我自己也写了些,人家的地址我也放开头了,这里就先投原创了,有问题的话可以留言联系我)。
本文通过实例解析Java静态代理与动态代理的工作原理,展示了如何使用代理模式简化类的扩展,重点讲解了动态代理的StuInvocationHandler实现和Proxy.newProxyInstance方法的应用。
3294





