静态代理
静态代理主要由一个公共接口,一个具体的类,一个代理类组成。代理类持有具体类的实例。代理的是具体类的实例方法。
公共接口:
public interface Person {
// 上交班费
void giveMoney();
}
具体类:
public class Student implements Person {
private String name;
public Student(String name) {
this.name = name;
}
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() {
stu.giveMoney();
}
}
为什么要用代理类去调用具体类的方法?引入这种间接性的好处?
不直接调用实际对象的方法,我们在代理过程中就可以加上一些其他用途。比如,在上交班费前记录下。
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.getName() + "学习上有很大进步");
stu.giveMoney();
}
}
然而静态定理只实现了对特定类的代理,如这里只实现了对Student
类的代理,如果还有其他的类呢,都要写一个代理类?而且在多个实现类中如果都要记录下日志,对每个实现类都要多写个日志代码,显得很冗余,且业务逻辑与日志没有解耦,于是动态代理就是解决这个问题。
动态代理
在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。
接口与具体类与静态代理相同
代理类
public class StuInvocationHandler<T> implements InvocationHandler {
// 代理对象
T target;
public StuInvocationHandler(T target) {
this.target = target;
}
public <T> T getProxy(Class<T> clazz){
//创建代理对象
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" +method.getName() + "方法");
Object result = method.invoke(target, args);
return result;
}
}
测试
public class ProxyTest {
public static void main(String[] args) {
Student wdcp = new Student("wdcp");
StuInvocationHandler<Person> stuInvocationHandler = new StuInvocationHandler<Person>(wdcp);
// 创建代理对象
Person stuProxy = stuInvocationHandler.getProxy(Person.class);
stuProxy.giveMoney();
}
}
如此一来,就可以解决上面静态代理的两个问题:
1、不必为每个实现类编写一个代理类,通过泛型动态创建具体类的代理对象。
2、当多个实现类中都需要添加日志或者其他信息时,不需要在每个实现类中添加,在invoke方法中添加一条后即可。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1216271933@qq.com