所谓的代理模式就是指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理。就好像一个公司的老板需要开会一样,老板(真实主题)来主持会议,老板的秘书(代理主题)负责开会前的准备性工作以及会后的相关事宜的处理。无论是老板的会议主持,还是秘书为会议的准备或会后事宜处理,共同的目的都是为了开会。
静态代理实现
package com.qwy;
/**
* @author qwy
* @create 2021-03-30 22:06
**/
interface Meeting{
public void meet();
}
class Boss implements Meeting{
@Override
public void meet() {
System.out.println("老板主持开会");
}
}
class Secretary implements Meeting{
private Meeting meeting;
public Secretary(Meeting meeting) {
this.meeting = meeting;
}
@Override
public void meet() {
this.ready();
this.meeting.meet();
this.end();
}
public void ready(){
System.out.println("秘书负责会议之前的准备工作");
}
public void end(){
System.out.println("秘书整理会后事宜");
}
}
public class TestProxy {
public static void main(String[] args) {
Meeting boos= new Boss();
Secretary proxy=new Secretary(boos);
proxy.meet();
}
}
运行结果:
秘书负责会议之前的准备工作
老板主持开会
秘书整理会后事宜
动态代理实现
上例的静态代理,每一个代理类只能为一个接口服务,最好的方式就是可以通过一个类完成全部的代理工作,JDK为我们提供动态代理。在java中实现动态代理需要以下接口和类的支持:
1.java.lang.reflect.InvocationHandler接口
package java.lang.reflect;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
参数:
Object proxy:被代理的对象
Method method:要调用的方法
Object[] args:方法调用时需要的参数
2.java.lang.reflect.Proxy类
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态生成实现类。提供的操作方法:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
通过该方法可以动态生成实现类,参数:
ClassLoader loader:目标类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口子类实例。
实例:
package com.qwy2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author qwy
* @create 2021-03-30 22:21
**/
interface Meeting{
public void meet();
}
class Boos implements Meeting{
@Override
public void meet() {
System.out.println("老板主持开会");
}
}
class Secretary implements InvocationHandler {
//真实业务类对象
private Object target;
/**
* 进行真实业务对象与代理业务对象之间的绑定处理
* @param target
* @return
*/
public Object bind(Object target){
this.target=target;//保存真实业务对象
/**
* Proxy.newProxyInstance(loader,interfaces,h)的参数
* loader - 定义代理类的类加载器
* interfaces - 代理类要实现的接口列表
* h - 指派方法调用的调用处理程序
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
public void ready(){
System.out.println("秘书负责会议之前的准备工作");
}
public void end(){
System.out.println("秘书整理会后事宜");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.ready();
/**
* method:为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
* this.target:被代理类的对象
* args:传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null
*/
Object resultData= method.invoke(this.target, args);
this.end();
return resultData;
}
}
public class TestProxy {
public static void main(String[] args) {
Meeting meeting= (Meeting) new Secretary().bind(new Boos());
meeting.meet();
}
}
运行结果:
秘书负责会议之前的准备工作
老板主持开会
秘书整理会后事宜