1、代理的概念
代理模式作用:为其他对象提供一种代理以控制对这个对象的访问。代理对象可以在客户端与目标对象之间起到中介作用。代理可以在不改动目标对象的基础上,增加额外的功能(扩展功能)(这应该是代理的实际作用)。
2、三种代理模式
2.1 静态代理
抽象角色:真实对象和代理对象的共同接口
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。代理对象在操作真实时,可以附加其他的操作。
真实角色:代理角色所代表的的真实对象,是我们最终要引用的对象。
1.抽象角色
/**
* 真实对象要实现的接口
* */
public interface Subject {
void request();
}
2.真实角色
/**
* 真实对象实现接口
* */
public class RealSubject implements Subject{
@Override
public void request() {
System.out.println("欢迎访问我");
}
}
3.代理角色
/**
* 代理角色
* 实现抽象角色
* */
public class SubjectProxy implements Subject{
private RealSubject realSubject;//以真实角色做为代理角色的属性
public SubjectProxy() {
}
@Override
public void request() {
//执行真正方法前做一些其他业务逻辑(相当于扩张)
System.out.println("执行真正方法前做一些其他业务逻辑");
if(realSubject == null) {
realSubject = new RealSubject();
}
realSubject.request();//执行真实对象的方法
System.out.println("执行真正方法后做一些其他业务逻辑");
}
}
客户端:
Subject sub = new SubjectProxy();
sub.request();执行真正方法前做一些其他业务逻辑
欢迎访问我
执行真正方法后做一些其他业务逻辑
由以上代码可以看出,客户实际需要调用的是RealSubject类的request()方法,现在用SubjectProxy来代理RealSubject类,同样达到目的。从上面的代码可以看出一个真实角色需要对应一个代理角色,若真实角色需要增加一个业务需求,那代理类同样得实现这个需求,会造成代码的臃肿,不利于扩展。
2.2 动态代理(JDK代理)
代理类在程序运行时创建的代理方式被称为动态代理。也就是说,代理类并不需要在Java代码中定义,而是在运行时动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
2.2.1 特点
1.代理对象不需要实现实现抽象角色接口
2.代理对象的生成,是利用JDK的API,动态的在内存中创建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
3.动态代理也叫做:JDK代理,接口代理
抽象角色和真实角色参考《静态代理》的代码
代理角色
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SubjectProxy implements InvocationHandler{
private Object target;//维护一个目标对象
public SubjectProxy(Object target) {
this.target = target;
}
/**
* @param 代理对象
* @param 目标对象的方法
* @param 目标对象的方法的参数
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前我先做点其他事");
//执行目标对象的方法
method.invoke(target, args);
System.out.println("执行后我再做点其他事");
return null;
}
/**
* 获取代理的对象
* */
public Object getProxyInstance() {
/**
* @param 用来指明生成代理对象使用哪个类装载器
* @param 用来指明生成哪个对象的代理对象,通过接口指定
* @param 用来指明产生的这个代理对象要做什么事情
* static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
* */
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}
客户端调用:
//目标对象
Subject target = new RealSubject();
//给目标对象创建代理
Subject proxy = (Subject) new SubjectProxy(target).getProxyInstance();
//执行方法(代理对象)
proxy.request();
JDK动态代理大体可分为以下四个步骤:
- 创建抽象角色
- 创建真实角色
- 通过实现InvocationHandler接口创建中介类
- 通过场景类,动态生成代理类
JDK代理源码稍后分析,目前正在研究中。。。。