静态代理
代理类
+被代理类
+公共接口
公共接口
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) {
// 检测是否为Student对象
if(stu.getClass() == Student.class) {
this.stu = (Student)stu;
}
}
//代理上交班费,调用被代理学生的上交班费行为
public void giveMoney() {
//可以加其他语句
stu.giveMoney();
}
}
具体实现
public class StaticProxyTest {
public static void main(String[] args) {
//被代理的学生张三,他的班费上交有代理对象monitor(班长)完成
Person zhangsan = new Student("张三");
//生成代理对象,并将张三传给代理对象
Person monitor = new StudentsProxy(zhangsan);
//班长代理上交班费
monitor.giveMoney();
}
}
动态代理
1. 基础知识
Proxy
类:提供了创建动态代理类和实例的静态方法
static InvocationHandler getInvocationHandler(Object proxy)
:- 返回指定代理实例的调用程序
static 类<?> getProxyClass(ClassLoader loader, 类<?>... interfaces)
:- 给出类加载器和接口数组的代理类的 java.lang.Class对象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
- loader:类加载器 - interfaces:代理对象绑定的接口,可以有多个 - h:代理对象的逻辑实现
InvocationHandler
接口:实现代理对象的逻辑
/**
* @param proxy 代理对象
* @param method 当前方法
* @param args method方法的运行参数
* @return 方法调用结果
*/
public Object invoke(Object proxy,Method method,Object[] args);
2. 实例
仍然以交班费为例,公共接口:
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元");
}
}
①创建代理类
创建StuInvocationHandler
类,实现InvocationHandler
接口,这个类中包含被代理对象的实例target
。所有执行target
的方法都会被替换成执行类中的invoke
方法
public class StuInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的被代理对象
T target;
//构造方法
public StuInvocationHandler(T target) {
this.target = target;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"方法开始执行...");
Object result = method.invoke(target, args);
System.out.println(method.getName()+"方法执行结束...");
return result;
}
}
② 创建动态实例
通过
getProxyClass
//创建一个与代理对象相关联的 InvocationHandler
InvocationHandler stuHandler = new StuInvocationHandler<Person>(stu);
//使用 getProxyClass 生成动态代理类 stuProxyClass
Class<?> stuProxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class<?>[] {Person.class});
//获得stuProxyClass中一个带 InvocationHandler 参数的构造器 constructor(忘记了看反射那部分)
Constructor<?> cons = stuProxyClass.getConstructor(InvocationHandler.class);
//通过构造器cons创建动态实例 stuProxy
Person stuProxy = (Person) cons.newInstance(stuHandler);
通过
newProxyInstance
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler stuHandler = new StuInvocationHandler<Person>(stu);
//创建一个代理对象stuProxy,代理对象的每个执行方法都会替换执行stuHandler中的invoke方法
Person stuProxy= (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
③ 测试
public class ProxyTest {
public static void main(String[] args) {
//1.
//创建一个实例对象,这个对象是被代理的对象
Person zs = new Student("张三");
//2.
//通过 newProxyInstance 创建动态实例
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler stuHandler = new StuInvocationHandler<Person>(zs);
//创建一个代理对象stuProxy来代理zs,zs的每个执行方法都会替换执行stuHandler中的invoke方法
Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
//3.
//代理执行上交班费的方法
stuProxy.giveMoney();
}
}
/*
输出:
giveMoney方法开始执行...
张三上交班费50元
giveMoney方法执行结束...
*/