静态代理

代理类+被代理类+公共接口

公共接口

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方法执行结束...
*/