| 
 
| 下面我们来看客户端: Action action = (Action)ProxyAction.getInstance(new ViewAction());
 Action.doAction();
 我们可以看到代理类对接口的依赖也转移到了客户端上,这样,代理类不依赖于某个接口。对于同样的代理类ProxyAction,我们也可以有如下的客户端调用:
 Engine engine = (Engine)ProxyAction.getInstance(new EngineImpl());
 Engine.execute();
 只要engineImpl类实现了Engine接口,就可以像上面那样使用。
 现在我们可以看到,动态代理的确是拥有相当的灵活性。但我们同时也看到了,这个代理类写起来比较麻烦,而且也差不多每次都写这样千篇一律的东西,只有委派前的动作和委派后的动作在不同的代理里有着不同,其他的东西都需要照写。如果这样的代理类写多了,也会有一些冗余代理。需要我们进一步优化,这里我们使用模板方法模式来对这个代理类进行优化,如下:
 public abstract class BaseProxy implements InvocationHandler {
 private Object obj;
 protected BaseProxy(Object obj)
 {
 this.obj = obj;
 }
 public static Object getInstance(Object obj,InvocationHandler instance)
 {
 return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
 obj.getClass().getInterfaces(),instance);
 }
 
 public Object invoke(Object proxy, Method m, Object[] args)
 throws Throwable {
 // TODO Auto-generated method stub
 Object result;
 
 try {
 
 System.out.println("before method " + m.getName());
 this.doBegin();
 
 result = m.invoke(obj, args);
 
 } catch (InvocationTargetException e) {
 
 throw e.getTargetException();
 
 } catch (Exception e) {
 
 throw new RuntimeException("unexpected invocation exception: "
 
 + e.getMessage());
 
 } finally {
 
 System.out.println("after method " + m.getName());
 this.doAfter();
 
 }
 
 return result;
 
 
 }
 public abstract void doBegin();
 public abstract void doAfter();
 
 }
 这样,代理的实现类只需要关注实现委派前的动作和委派后的动作就行,如下:
 public class ProxyImpl extends BaseProxy {
 protected ProxyImpl(Object o)
 {
 super(o);
 }
 public static Object getInstance(Object foo)
 {
 return getInstance(foo,new ProxyImpl(foo));
 }
 
 //委派前的动作
 public void doBegin() {
 // TODO Auto-generated method stub
 System.out.println("begin doing....haha");
 
 }
 
 //委派后的动作
 public void doAfter() {
 // TODO Auto-generated method stub
 System.out.println("after doing.....yeah");
 
 }
 
 }
 从上面的代码,我们可以看出代理实现类的确是简单多了,只关注了委派前和委派后的动作,这是我们作为一个代理真正需要关心的。
 至此,代理模式和动态代理已经告一段落。我们将动态代理引申一点说开去,来作为这篇文章的蛇足。
 这个话题就是面向方面的编程,或者说AOP。我们看上面的ProxyImpl类,它的两个方法doBegin()和doAfter(),这是做核心动作之前和之后的两个截取段。正是这两个截取段,却是我们AOP的基础。在OOP里,doBegin(),核心动作,doAfter()这三个动作在多个类里始终在一起,但他们所要完成的逻辑却是不同的,如doBegin()可能做的是权限,在所有的类里它都做权限;而在每个类里核心动作却各不相同;doAfter()可能做的是日志,在所有的类里它都做日志。正是因为在所有的类里,doBegin()或doAfter()都做的是同样的逻辑,因此我们需要将它们提取出来,单独分析、设计和编码,这就是我们的AOP的思想。
 这样说来,我们的动态代理就能作为实现AOP的基础了。好了,就说这么多,关于AOP技术,我们可以去关注关于这方面的知识。
 
 
 
 | 
 |