论坛首页 Java企业应用论坛

实现代理的四种方式

浏览 4749 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-31  

代理可以分为静态代理和动态代理,前者由开发人员自己编写,后者由工具生成。

在具体实现时,又有实现接口方式和继承方式的区别。

以下对这2种组合共4种方式做个简单说明:

1。静态代理,实现接口方式。即GoF的Proxy parttern。

通过代理对象和被代理的对象实现同一接口来实现。

例如

java 代码
  1. public interface BookDao {   
  2.   
  3.     List queryByName(String bookName);   
  4.        
  5.     Book getByIsdn(String isdn);   
  6. }  
java 代码
  1. public class BookDaoImpl implements BookDao {   
  2.   
  3.     public Book getByIsdn(String isdn) {   
  4.         // 完成取数据操作   
  5.         return null;   
  6.     }   
  7.   
  8.     public List queryByName(String bookName) {   
  9.         // 完成取数据操作   
  10.         return null;   
  11.     }   
  12.   
  13. }  
java 代码
  1. public class BookDaoLogProxy implements BookDao{   
  2.     private Logger logger=Logger.getLogger("BookDaoLogProxy");   
  3.        
  4.     private BookDao bookDao;   
  5.     public void setBookDao(BookDao bookDao) {   
  6.         this.bookDao = bookDao;   
  7.     }   
  8.        
  9.     public Book getByIsdn(String isdn) {   
  10.         logger.info("getByIsdn: "+isdn);   
  11.         return bookDao.getByIsdn(isdn);   
  12.     }   
  13.   
  14.     public List queryByName(String bookName) {   
  15.         logger.info("queryByName: "+bookName);   
  16.         return bookDao.queryByName(bookName);   
  17.     }   
  18.   
  19. }  

BookDaoLogProxy是代理类,在使用时,把BookDaoImpl的对象注入到BookDaoLogProxy的实例中即可。

这种方式大家都比较熟悉。

2。动态代理,实现接口的方式。

在JDK1.3起,java就支持动态代理的创建,但是对被代理的对象有一个要去就是必须实现了接口。

java 代码
  1. import java.lang.reflect.InvocationHandler;   
  2. import java.lang.reflect.Method;   
  3. import java.lang.reflect.Proxy;   
  4.   
  5. public class LogProxyFactory implements InvocationHandler {   
  6.     private static Logger logger = Logger.getLogger("TransactionProxyFactory");   
  7.   
  8.     private Object target = null;   
  9.        
  10.     private LogProxyFactory(Object target) {   
  11.         this.target = target;   
  12.     }   
  13.   
  14.     public Object invoke(Object proxy, Method method, Object[] args)   
  15.             throws Throwable {   
  16.         logger.info("<invoke></invoke> " + target.getClass().getName() + ": "  
  17.                 + method.toGenericString());   
  18.         Object rv = null;   
  19.         rv = method.invoke(target, args);   
  20.         return rv;   
  21.     }   
  22.   
  23.     public static Object getProxy(Object target) {   
  24.         InvocationHandler handler = new LogProxyFactory(target);   
  25.   
  26.         Object proxy = Proxy.newProxyInstance(target.getClass()   
  27.                 .getClassLoader(), target.getClass().getInterfaces(), handler);   
  28.         return proxy;   
  29.     }   
  30. }  

LogProxyFactory是一个动态代理的工厂,只需调用getProxy(bookDaoImpl)即可得到BookDaoImpl的动态代理(bookDaoImpl是BookDaoImpl的实例)。

关于动态代理,更多的资料请看相关的文档或者书籍。

3。静态代理,继承方式。

通过继承被代理的对象并覆盖它的方法来实现代理的目的。

例如:

java 代码
  1. public class BookDao {   
  2.   
  3.     public Book getByIsdn(String isdn) {   
  4.         // 完成取数据操作   
  5.         return null;   
  6.     }   
  7.   
  8.     public List queryByName(String bookName) {   
  9.         // 完成取数据操作   
  10.         return null;   
  11.     }   
  12.   
  13. }  
java 代码
  1. public class BookDaoLogProxy extends BookDao {   
  2.     private Logger logger=Logger.getLogger("BookDaoLogProxy");   
  3.        
  4.     public Book getByIsdn(String isdn) {   
  5.         logger.info("getByIsdn: "+isdn);   
  6.         return super.bookDao.getByIsdn(isdn);   
  7.     }   
  8.   
  9.     public List queryByName(String bookName) {   
  10.         logger.info("queryByName: "+bookName);   
  11.         return super.bookDao.queryByName(bookName);   
  12.     }   
  13.   
  14. }  

这样的实现方式不需要代理类和被代理的对象实现任何接口,且代理类可以使用被代理对象的保护资源。但是代理类和被代理的对象有紧密的耦合。

4。动态代理,继承方式。

这种方式需要字节码生成的第三方工具来实现,原理即通过覆盖父类的方法来实现代理。

Hibernate对PO就是使用了这样的方式来使在PO的数据改变时,Hibernate能对数据库中的数据进行更新。

字节码生成我也没玩过,这里就不举例子了。

 

总结一下,

通过实现接口的方式,优点是代理类和被代理的对象耦合度比较低,而且遵循面向接口编程的原则。

通过继承方式的优点则是不需要实现接口,且能使用被代理的对象的资源,但是耦合紧密。

动态代理相对于静态代理来说,减少了代码的重复。

以上即实现代理的四种方式,说的不是很详细,如果有不对的地方,请指正。

   发表时间:2007-06-01  
字节码增强,类似于动态代理,也是在运行期产生一个类。用于实现拦截等功能,看了tapestry ioc中,就是这么实现的。
0 请登录后投票
   发表时间:2007-06-01  
动态代理的优点应该还有:静态代理方式,代理类要去预先实现接口的所有方法;动态代理方式下,可以运行期动态分析接口中有哪些方法,并结合InvocationHandler的invoke方法去代言执行被代理对象中的方法。
但是相比静态代理,代理执行的内容都在InvocationHandler的invoke一个方法中是不是变得太臃肿了。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics