Java与代理———静态代理与动态代理

从代理模式开始

代理模式作为设计模式的一种,在实际编程应用中有着很多的用处。目前主流使用的Spring框架AOP的实现便是通过动态代理来实现的。博主最近准备研究一下Spring底层源码,首先便由代理模式开始。
代理模式的UML类图可以简单描述如下:
proxy
由类图中我们可以看出,要被代理的真实类和代理类都需要实现一个接口,接口中定义的方法可以在代理类中进行增强与扩展。静态代理就是这么做的。

静态代理

在静态代理的实现中,主要思路便是构造一个持有要被代理的真实类的一个引用,然后通过自身对于接口的实现,来进行增强与扩展。示例代码如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.jayden.proxy;
/**
* Created by Jayden Ransom on 2017/7/22.
* 接口定义,定义sale()方法
*/
public interface Produce {
public void sale();
}
/**
* Created by Jayden Ransom on 2017/7/22.
* 被代理类定义,实现Produce接口
*/
public class Producer implements Produce{
@Override
public void sale() {
System.out.println("Producer:卖出了一个货物");
}
}
/**
* Created by Jayden Ransom on 2017/7/22.
* 代理类定义,实现Produce接口,同时内部持有一个被代理类的引用
*/
public class ProducerProxy implements Produce {
private Produce produce;
public ProducerProxy(Produce produce) {
this.produce = produce;
}
@Override
public void sale() {
//添加增强
proxy();
produce.sale();
}
//增强方法的定义
private void proxy() {
System.out.println("商店代理销售");
}
}
/**
* Created by Jayden Ransom on 2017/7/22.
* //测试类,进行代理测试
*/
public class Buyer {
public static void main(String[] args) {
Produce producer = new Producer();
Produce proxy = new ProducerProxy(producer);
//调用代理类的sale方法,运行增强后的行为
proxy.sale();
}
}
运行结果如下:
商店代理销售
Producer:卖出了一个货物

上例中,我们主要要完成一个简单的售货逻辑。在现实社会中,我们的售货主要是由商店进行代理。本例中,首先定义了Produce接口,该接口对售货行为进行了约束;Producer类为真正的生产者类,货物是由他们生产的。ProducerProxy类作为代理,在该类的方法实现中,实现了对于方法的增强。
在主方法中,我们定义了一个代理类和一个被代理类,通过调用代理类的方法,实现了方法的增强。由于被代理类和代理类均实现了同一接口,所以所有需要用被代理的地方均可以使用代理类进行代理。
以上便是静态代理的基本实现。即定义代理类与被代理类实现相同接口,在代理类的方法实现中进行方法的增强。

动态代理

由上例可以看出,我们可以通过静态代理的方式对方法进行增强。但是如果方法变多或者接口发生变化,那么代理类中就要对这些方法进行重新实现,这是很麻烦的过程,所以静态代理应用的场景很有局限性。
在静态代理基础上,Java语言提供了动态代理机制。动态代理主要用到了Java语言的反射机制,即在运行时期获得类信息、并动态创建对象。
目前主要的动态代理实现主要有两种:一种为jdk原生动态代理;另一种为使用cglib这一code生成库实现动态代理。
原生动态代理与静态代理一样,均需要通过接口进行。这是由于Java的继承机制引起的,关于这部分内容还会在后期开新的博客。而使用cglib实现的动态代理则摆脱了接口的束缚。
Spring AOP的实现中,同时用到了这两种动态代理。关于具体二者的实现与区别,将在下一篇博文中介绍。