Proxy机制(java动态代理机制)

什么是动态代理?

java动态代理机制

  • Q1:什么叫做动态代理机制?
  • Q2:动态代理机制有什么好处?
  • Q3:什么地方用到动态代理?

动态代理的源码在java.lang.reflect这个包里,应该是Proxy类。里面有提供两个静态方法:


1.Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)

用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”,
用来冒充真实的对象。

2.Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),
它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(…)方法,所以在
invoke方法中,我们可以做很多事情。


“动态”是针对静态编码而言的,可以是编译器、类装载器和运行期。

引一个大大的例子来说下自己的理解:比如有有一个接口A,里面有方法sayHello(),print()方法。然后一个B类(AIml类)来实现
具体实现A接口,然后再写一个代理类,伪装成B类,代理类里面通过动态的实现B类的方法(其实就是通过反射实现的B类方法),
然后外面的请求发过来之后,都是通过代理类来处理,方便集中处理一系列的方便的集成权限控制,异常处理,事务控制,
性能统计等等(这里感谢 方老师 对我指点)

然后下面是一个网上大大对动态代理的画的图,大家参考一下很明了的关系图。

A接口

1
2
3
4
public interface A {
public void sayHello(String to);
public void print(String p);
}

B类(实现A接口)

1
2
3
4
5
6
7
8
9
10
11
12
13
public class AImpl implements A{
@Override
public void sayHello(String to) {
System.out.println("Hello:"+to);
}
@Override
public void print(String p) {
System.out.println("print:"+p);
}
}

C类(代理类,伪装成B类)

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
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class Handler implements InvocationHandler{
private Object obj;
public Handler(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
doBefore();
Object result = method.invoke(obj, args);
doAfter();
return result;
}
private void doAfter() {
System.out.println("after...");
}
private void doBefore() {
System.out.println("before...");
}
}

测试类:D类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.lang.reflect.Proxy;
public class ProxyTester {
public static void main(String[] args) {
A impl = new AImpl();
Handler handler = new Handler(impl);
//这里把handler与impl新生成的代理类相关联
A hello = (A) Proxy.newProxyInstance(impl.getClass().getClassLoader(),
impl.getClass().getInterfaces(), handler);
//这里无论访问哪个方法,都是会把请求转发到handler.invoke
hello.print("All the test");
hello.sayHello("SunnyZhu");
}
}

测试结果如下:

1
2
3
4
5
6
before...
print:All the test
after...
before...
Hello:zhushiqing
after...

自此代码就实现了,在hello(A类)调用的动态方法都是集中交给代理类来处理了。方便在代理类集中处理一些事情,before 干点啥,after干点啥。


最后回答下三个Questions

A1:一种用于转发请求,进行特殊处理的机制,这里的动态是针对静态编码而言的,可以是编译器、类装载器和运行期。

A2:方便的集成权限控制,异常处理,事务控制,性能统计等等

A3:很多地方,web层的controller,biz层的service,都会使用动态代理,目的在于实现aop,


学习了java动态代理,与诸君共勉!