代理设计模式的核心含义在于一个业务操作除了真实实现之外,也需要有代理支持,代理负责所有与真实操作有关的辅助性功能实现,而真实主题只负责核心业务操作。
代理使用分析:
在传统编写DAO程序操作过程之中,一直是存在有一个问题的,业务层的真实功能是调用数据层,但是发现在我们之前写的代码之中,业务层除了要调用数据层组织数据之外,还要负责数据库的打开和关闭。
范例:定义业务层接口
1 2 3 4 | package com.zmcheng.Demo; public interface Service { public void print() throws Exception; } |
范例:定义真实主题类
1 2 3 4 5 6 7 8 9 | package com.zmcheng.Demo; public class ServiceImpl implements Service { @Override public void print() throws Exception { System.out.println("********操作前的准备:打开数据库连接*******"); System.out.println("********操作数据层的若干操作*******"); System.out.println("********操作后的收尾:关闭数据库连接*******"); } } |
以上是最早的设计思路,但是如果说现在结合代理设计模式来看,实现就非常槽糕了,因为所有的核心业务操作业务与辅助业务都同时写在了一个方法里。必须解决这样的问题。
范例:设计一个静态代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.zmcheng.Demo; public class SeriverProxy implements Service { Service service; public SeriverProxy(Service service){ this.service = service; } public void pre() throws Exception{ System.out.println("********操作前的准备:打开数据库连接*******"); } public void end() throws Exception{ System.out.println("********操作后的收尾:关闭数据库连接*******"); } public void print() throws Exception { this.pre(); this.service.print(); this.end(); } } |
范例:真实主题实现类
1 2 3 4 5 6 7 | package com.zmcheng.Demo; public class ServiceImpl implements Service { @Override public void print() throws Exception { System.out.println("********操作数据层的若干操作*******"); } } |
而在使用的时候应该也通过工厂类取得接口实例化对象。
范例:定义serviceFactory
1 2 3 4 5 6 | package com.zmcheng.Demo; public class serviceFactory { public static Service getServiceInstance(){ return new SeriverProxy(new ServiceImpl()); } } |
此时继续编写客户端,客户端依然是通过工厂取得接口实例化对象,客户端不会关心是代理主题还是真实主题,只是它知道,利用你这个工厂的方法就可以取得Seriver接口,就可以操作了。
范例:编写客户端
1 2 3 4 5 6 7 | package com.zmcheng.Demo; public class Test { public static void main(String[] args) throws Exception{ Service service = serviceFactory.getServiceInstance(); service.print(); } } |
这个时候的代理发生了作用,也就是说在实际的环境之中,代理设计模式应该和工厂设计模式联合起来,这样客户端在操作的时候就不会有任何的不适应感。
动态代理设计模式:
使用代理模式可以有效的抽取出核心业务与辅助业务,但是回顾整个项目的开发过程里面,可能会存在几百个业务层接口。可是这个时候所有的代理层的功能发现都一样,都只是负责真实主题业务调用,以及打开关闭数据库。如果每一个业务层接口都编写一个代理,基本上的表现:代理也是折磨人的。所以必须想办法让一个代理类可以负责所有真实主题的操作。
如果想要实现动态代理设计模式,必须有一个类来实现java.lang.reflect InvocationHandler接口。此接口有一个方法:
Object invoke(Object proxy, Method method,Object[] args) throws Throwable
实际上invoke()这个方法是属于反射调用的方法,证明动态代理也属于反射调用,而在invoke方法里面参数:
Object proxy:表示要代理的对象;
Method method:表示要操作的方法;
Object args[]:方法调用时传递的参数。
如果要想让代理设计真正可以使用,必须有一个代理类对象产生,而这个代理类对象的产生可以通过java.lang.reflect.Proxy类完成,而在Proxy类里面有一个取得代理对象的实例化方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
throws IllegalArgumentException
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.zmcheng.Demo; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ServiceProxy implements InvocationHandler { private Object target=null; public Object getProxy(Object obj){ this.target = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } public void prepare(){ System.out.println("********操作前的准备:打开数据库连接*******"); } public void end() throws Exception{ System.out.println("********操作后的收尾:关闭数据库连接*******"); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object retValue = method.invoke(this.target, args); return retValue; } } |
下篇博客将对剖析动态代理类的原理。