浅谈动态代理
动态代理是Java中提供的一种动态的实现代理模式的方法,使得开发人员无需手工的编写代理类。要谈动态代理,还是要先介绍何为代理设计模式。
代理模式
代理模式主要是为了在主体与真正要执行的操作之间,添加了一个中间层,使得可以使请求在代理人这里先做处理,无法处理时再调用真正的主体;又或者可以在真正调用主体方法时执行一些额外的操作。例如我们有如下的代码: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
28interface Subject {
void saySomething(String str);
void doSomething(Thing t);
}
pubic calss RealSubject implements Subject {
void saySomething(String str) {
System.out.println(str);
}
void doSomething(Thing t) {
System.out.println(t.title);
}
}
public class subjectProxy implements subject {
Subject sbj;
subjectProxy(Subject s) {
sbj = s;
}
void saySomething(String str) {
System.out.println("Say something else====");
sbj.saySomething(str);
}
void doSomething(Thing t) {
System.out.println("Do something else====");
System.out.println(t.title);
}
}
以上代码中,Subject是使Proxy和RealSubject具有一致性的接口,实现了这个接口,调用者就不必在意使用的是Proxy还是RealSubject。Proxy在处理用户请求时,先执行了自己的一些操作,然后才调用RealSubject完成调用者的请求。
代理同时也可作为缓存,例如在HTTP中就有代理,如果用户的请求在代理中有缓存的话,就直接返回缓存,否则的话才去服务器真正的获取自己请求的内容。
因此,代理设计模式还是十分有用的。但是静态代理有一些弊端,比如要代理许多功能相似的类,那么就要手工的编写许多的代理类,显得十分繁琐,所以Java使用动态代理来完成这样的任务。
动态代理
动态代理实现的也是代理设计模式,只是其灵活性被大大加强。先看使用动态代理实现上述例子中代理的代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14public class SbjProxyHandler implements InvocationHandler {
private Object proxied;
SbjProxyHandler(Object o) {
proxied = o;
}
public Object invoke(Object proxy, Method method, Object[] args) {
//Something u can do here
Object result = method.invoke(proxied, args);
//some other things can do here
return result;
}
}
SbjProxyHandler是一个调用处理器,我们通过下面的代码获取动态代理类:1
2
3
4
5
6
7
8
9calss proxyTest {
public static void main(String[] args) {
RealObject real = new RealObject();
Subject sb = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
new class[]{ Subject.class; },
new SbjProxyHandler(real));
sb.saySomething();
}
}
动态代理类主要通过Proxy.neProxyInstance方法来实现的,其中第一个方法是实体类的类加载器,第二个参数是要实现的接口的数组列表,第三个则是要使用的调用处理器的实现。
通过动态代理类进行的调用,都会先进入到invoke()方法中执行,然后根据情况分发到主体类中。Spring中AOP的实现就是使用动态代理来完成的。
我们可以在invoke()函数中定义我们自己的调用逻辑,例如将AOP的信息写在主体操作执行的前面和后面,这样就可以收集到具体的信息。
同时动态代理还有一个优点,因为不需要创建每个主体类的代理类,所以Proxy的代码不会越来越庞大。