代理模式:客户端并不直接访问服务端,而是通过调用代理,来间接调用实际的对象。
有两种实现方式:
-
静态代理:
代理类和目标类是确定的;
在不修改目标对象功能的前提下,对目标功能进行扩展;
-
动态代理:根据代理对象,动态的创建代理类。本质是通过反射实现的
public interface Person {
//交作业
void giveTask();
}
public class Student implements Person {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void giveTask() {
System.out.println(String.format("%s交语文作业", name));
}
}
/**
* 每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,
* 当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke方法来进行调用。
*/
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() + "方法");
return method.invoke(target, args);
}
动态代理测试:
@Test
public void dynamicProxy() {
//创建一个实例对象,这个对象是被代理的对象
Person linqian = new Student("林浅");
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler stuHandler = new StuInvocationHandler<>(linqian);
//创建一个代理对象stuProxy来代理linqian,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
// 代理执行交作业方法
stuProxy.giveTask();
}
静态代理与动态代理的区别
- 静态代理只能通过手动完成代理操作,如果被代理类增加了新方法,代理类需要同步增加,违背了开闭原则;
- 动态代理采用在运行时动态生成代码的方式,取消了被代理类的扩展限制,遵循开闭原则;
- 若动态代理对目标类进行增强逻辑扩展,只需要新增策略便可完成,无需修改代理类代码;