# 代理模式

# 1.基本概念

名词解释:代理类、被代理类、代理对象、被代理对象

【代理模式】 就是在不改变原有类(被代理类)的情况下,为原有类创建代理对象,对原有类的功能做增强的一种模式。

# 1.1代理模式的优点:

  1. 满足单一原则,业务类可以只关心自己的核心逻辑,非核心逻辑由代理类完成;
  2. 易于维护,核心逻辑、非核心逻辑的修改不会互相影响;
  3. 对于用户(调用者)而言,使用的方式没有区别,可以做到低成本替换;
  4. JDK动态代理可以动态的绑定目标类,可以减少代码量,提高代码的复用;
  5. cglib动态代理可基于实现类做代理,可以解决JDK代理依赖接口的问题;

# 1.2代理模式的缺点:

  1. 静态代理每个被代理类都要有一个代理类,大大增加了代码量;
  2. JDK动态代理基于JDK的反射原理实现,降低了执行效率;
  3. JDK动态代理是基于接口的代理,要求目标类必须实现目标接口;

# 1.3代理模式分类:

  1. 静态代理

  2. JDK动态代理(基于目标类的接口生成代理类做代理)

    被代理类必须有接口,然后通过反射生成代理对象(代理对象的类和被代理对象的类实现相同接口)来完成额外的增强功能

  3. CGLib动态代理(基于目标类生成子类做代理,同时也支持基于接口的代理)

    不需要接口其利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成被代理对象的子类来完成额外的增强功能

# 1.4代理模式应用场景

我们知道,Spring的AOP就是依赖于动态代理模式实现的,那我们在日常的开发中有哪些地方能用到代理呢?

事物、日志、监控、统计、鉴权、限流、缓存、环境隔离、多数据源切换

# 2.静态代理

  1. 有个接口,有个实现类。
public interface SayService {
    public void say(String msg);
}
1
2
3
public class CowSayServiceImpl implements SayService {
    @Override
    public void say(String msg) {
        System.out.println("CowSayServiceImpl say" + msg);
    }
}
1
2
3
4
5
6
  1. 我们想再实现类执行方法之前做增强,那就整一个代理类,传入要代理的对象,对象执行方法之前之后都可以增强
public class MyProxyServiceImpl implements SayService {
    //要被代理的目标对象注入进来
    private CowSayServiceImpl cowSayService;
    public MyProxyServiceImpl( CowSayServiceImpl cowSayService) {
        this.cowSayService = cowSayService;
    }

    @Override
    public void say(String msg) {
        System.out.println("静态代理前置增强。。。。");
        this.cowSayService.say(msg); //目标方法执行
        System.out.println("静态代理后置增强。。。。");
    }
}

// 测试
MyProxyServiceImpl myProxyService = new MyProxyServiceImpl(new CowSayServiceImpl());
myProxyService.say("执行代码");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3.动态代理

# 3.1JDK 动态代理

  1. 有个接口,有个实现类。
public interface SayService {
    public void say(String msg);
}
1
2
3
public class CowSayServiceImpl implements SayService {
    @Override
    public void say(String msg) {
        System.out.println("CowSayServiceImpl say" + msg);
    }
}
1
2
3
4
5
6
  1. JDK动态代理

实现InvocationHandler接口,重新invoke方法使用Proxy.newProxyInstance产生代理对象 被代理的对象必须要实现接口

public class JdkDynamicProxy implements InvocationHandler {
    private Object target;

    public JdkDynamicProxy(Object target) {
        this.target = target;
    }

    //封装个方法
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this
        );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK 动态代理前置");
        Object invoke = method.invoke(target, args);
        System.out.println("JDK 动态代理后置");
        return invoke;
    }
}


// 测试
JdkDynamicProxy proxy2 = new JdkDynamicProxy(new CowSayServiceImpl());
SayService sayService = (SayService) proxy2.getProxyInstance();
sayService.say("hhhhhhh");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 3.2CGLib 动态代理

  1. 只需要一个类就行
public class CowSayServiceImpl {
    @Override
    public void say(String msg) {
        System.out.println("CowSayServiceImpl say" + msg);
    }
}
1
2
3
4
5
6
  1. 代理类
public class CglibDynamicProxy implements MethodInterceptor {

    private Object target;
    public CglibDynamicProxy(Object target) {
        this.target = target;
    }

    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("sss");
        Object invoke = methodProxy.invoke(target, objects);
        System.out.println("222");
        return invoke;
    }
}

//测试
CowSayServiceImpl cowSayService = new CowSayServiceImpl();
CglibDynamicProxy cglib = new CglibDynamicProxy(cowSayService);
SayService proxy = (SayService) cglib.getProxy();
proxy.say("cjloib");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28