代理模式
代理模式,为其他对象提供一种代理以控制对这个对象的访问。
代理模式的三种角色:
1. 抽象业务角色,抽象类或者接口;
2. 真实业务角色,继承或实现抽象业务角色,是业务的真正执行者。
3. 代理角色,控制真实业务角色,抽象类的方法,在真实业务角色中实现,可以在真实角色执行方法的过程前后加入预处理或者结束后的处理方法。
// 抽象业务角色
public abstract class Target {
// 业务方法
public abstract void method();
}
// 实际业务角色
public class RealTarget extends Target {
@Override
public void method() {
// 业务逻辑实现
}
}
// 代理类
public class Proxy extends Target {
private Target target = null;
// 构造方法传入实际角色
public Proxy(Target target){
this.target = target;
}
@Override
public void method() {
// 可以加入一些其他操作
this.before();
// 代理的业务方法调用的是实际角色的方法
target.method();
}
public void before(){
// 预处理
}
}
// 测试类
public class Test {
public static void main(String[] args) {
Target realTarget = new RealTarget();
Target proxy = new Proxy(realTarget);
proxy.method();
}
}
代理模式比较简单,使用也非常广泛。
动态代理模式
动态代理的主要意图就是在不改变已有代码结构的情况下增强或控制对象的行为,也就是横切面编程 AOP。
实例代码:
// 抽象角色
public abstract class Target {
// 业务方法
public abstract void method();
}
// 实际业务角色
public class RealTarget extends Target {
@Override
public void method() {
// 业务逻辑实现
}
}
// 通知接口
public interface Advice {
// 发通知方法
public void advice();
}
// 前置通知类
public class BeforeAdvice implements Advice{
@Override
public void advice() {
System.out.println("前置通知......");
}
}
// 动态代理的Handler类
public class MyInvocationHandler implements InvocationHandler{
// 被代理的真实角色
private Object target = null;
// 构造方法传入真实角色
public MyInvocationHandler(Object obj) {
this.target = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在代理方法中执行真实角色的方法
return method.invoke(this.target, args);
}
}
// 动态代理类
public class DynamicProxy<T> {
public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h){
// 切入点,加入前置通知
if(true){
new BeforeAdvice().advice();
}
// 返回代理
return (T) Proxy.newProxyInstance(loader, interfaces, h);
}
}
// 测试类
public class Test {
public static void main(String[] args) {
Target target = new RealTarget();
InvocationHandler handler = new MyInvocationHandler(target);
//通过动态代理获取代理,产生代理前会发送前置通知
Target proxy = DynamicProxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
// 代理执行真实角色的方法
proxy.method();
}
}
动态代理实现代理的职责, 业务逻辑 Target 实现相关的逻辑功能, 两者之间没有必然的相互耦合的关系。 通知 Advice 从另一个切面切入, 最终在高层模块进行耦合, 完成逻辑的封装任务。
对于日志、 事务、 权限等都可以在系统设计阶段不用考虑, 而在设计后通过AOP的方式切过去。