一、什么是代理模式
为其他对象提供一种代理以控制对这个对象的访问。
二、代理模式中的角色
1、Subject(抽象主题角色): 定义了RealSubject和Proxy的公共接口,这样就在任何使用RealSubject的地方都可以使用Proxy。
2、RealSubject(真实主题角色):定义Proxy所代表的真实实体。
3、Proxy(代理主题角色):保存一个引用使得代理可以访问实体,并提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体。
三、代理模式类图
四、代理模式代码(静态代理)
1、Subject
//公共接口
public interface Subject {
void request();
}
2、RealSubject
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject Request...");
}
}
3、Proxy
//代理对象
public class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
if (realSubject == null){
realSubject = new RealSubject();
}
before();
realSubject.request();
after();
}
public void before(){
System.out.println("Proxy before...");
}
public void after(){
System.out.println("Proxy after...");
}
}
4、客户端
public class MainClass {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.request();
}
}
五、JDK动态代理
Jdk的动态代理,是使用反射技术获得类的加载器并且创建实例,根据类执行的方法在执行方法的前后发送通知。在代理对象Proxy的新建代理实例方法中,必须要获得类的加载器、类所实现的接口、还有一个拦截方法的句柄。在句柄的invoke中如果不调用method.invoke则方法不会执行。在invoke前后添加通知,就是对原有类进行功能扩展了。缺点,被代理类必须实现接口。
Subject和RealSubject还是使用上面的,其他代码如下:
public class MainClass {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
MyHandler myHandler = new MyHandler();
myHandler.setRealSubject(realSubject);
//获得代理对象
Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), myHandler);
proxy.request();
}
}
class MyHandler implements InvocationHandler {
//真实对象的引用
private Object object;
public void setRealSubject(Object object) {
this.object= object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(object, null);
after();
return result;
}
public void before(){
System.out.println("Proxy before...");
}
public void after(){
System.out.println("Proxy after...");
}
}
六、Cglib动态代理
利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。因为是生成被代理类的子类,所以被代理类不能用final修饰。
被代理类:没有实现接口
public class RealSubject {
public void request() {
System.out.println("RealSubject Request...");
}
}
CglibProxy:
public class CglibProxy implements MethodInterceptor {
//维护目标对象
private Object target;
public CglibProxy(Object target) {
this.target = target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object result = method.invoke(target, objects);
after();
return result;
}
public void before(){
System.out.println("Cglib before...");
}
public void after(){
System.out.println("Cglib after...");
}
}
客户端:
public class MainClass {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy(new RealSubject());
RealSubject proxyInstance = (RealSubject) cglibProxy.getProxyInstance();
proxyInstance.request();
}
}