代理可以分为静态代理和动态代理,前者由开发人员自己编写,后者由工具生成。
在具体实现时,又有实现接口方式和继承方式的区别。
以下对这2种组合共4种方式做个简单说明:
1。静态代理,实现接口方式。即GoF的Proxy parttern。
通过代理对象和被代理的对象实现同一接口来实现。
例如
java 代码
- public interface BookDao {
-
- List queryByName(String bookName);
-
- Book getByIsdn(String isdn);
- }
java 代码
- public class BookDaoImpl implements BookDao {
-
- public Book getByIsdn(String isdn) {
-
- return null;
- }
-
- public List queryByName(String bookName) {
-
- return null;
- }
-
- }
java 代码
- public class BookDaoLogProxy implements BookDao{
- private Logger logger=Logger.getLogger("BookDaoLogProxy");
-
- private BookDao bookDao;
- public void setBookDao(BookDao bookDao) {
- this.bookDao = bookDao;
- }
-
- public Book getByIsdn(String isdn) {
- logger.info("getByIsdn: "+isdn);
- return bookDao.getByIsdn(isdn);
- }
-
- public List queryByName(String bookName) {
- logger.info("queryByName: "+bookName);
- return bookDao.queryByName(bookName);
- }
-
- }
BookDaoLogProxy是代理类,在使用时,把BookDaoImpl的对象注入到BookDaoLogProxy的实例中即可。
这种方式大家都比较熟悉。
2。动态代理,实现接口的方式。
在JDK1.3起,java就支持动态代理的创建,但是对被代理的对象有一个要去就是必须实现了接口。
java 代码
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
-
- public class LogProxyFactory implements InvocationHandler {
- private static Logger logger = Logger.getLogger("TransactionProxyFactory");
-
- private Object target = null;
-
- private LogProxyFactory(Object target) {
- this.target = target;
- }
-
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- logger.info("<invoke></invoke> " + target.getClass().getName() + ": "
- + method.toGenericString());
- Object rv = null;
- rv = method.invoke(target, args);
- return rv;
- }
-
- public static Object getProxy(Object target) {
- InvocationHandler handler = new LogProxyFactory(target);
-
- Object proxy = Proxy.newProxyInstance(target.getClass()
- .getClassLoader(), target.getClass().getInterfaces(), handler);
- return proxy;
- }
- }
LogProxyFactory是一个动态代理的工厂,只需调用getProxy(bookDaoImpl)即可得到BookDaoImpl的动态代理(bookDaoImpl是BookDaoImpl的实例)。
关于动态代理,更多的资料请看相关的文档或者书籍。
3。静态代理,继承方式。
通过继承被代理的对象并覆盖它的方法来实现代理的目的。
例如:
java 代码
- public class BookDao {
-
- public Book getByIsdn(String isdn) {
-
- return null;
- }
-
- public List queryByName(String bookName) {
-
- return null;
- }
-
- }
java 代码
- public class BookDaoLogProxy extends BookDao {
- private Logger logger=Logger.getLogger("BookDaoLogProxy");
-
- public Book getByIsdn(String isdn) {
- logger.info("getByIsdn: "+isdn);
- return super.bookDao.getByIsdn(isdn);
- }
-
- public List queryByName(String bookName) {
- logger.info("queryByName: "+bookName);
- return super.bookDao.queryByName(bookName);
- }
-
- }
这样的实现方式不需要代理类和被代理的对象实现任何接口,且代理类可以使用被代理对象的保护资源。但是代理类和被代理的对象有紧密的耦合。
4。动态代理,继承方式。
这种方式需要字节码生成的第三方工具来实现,原理即通过覆盖父类的方法来实现代理。
Hibernate对PO就是使用了这样的方式来使在PO的数据改变时,Hibernate能对数据库中的数据进行更新。
字节码生成我也没玩过,这里就不举例子了。
总结一下,
通过实现接口的方式,优点是代理类和被代理的对象耦合度比较低,而且遵循面向接口编程的原则。
通过继承方式的优点则是不需要实现接口,且能使用被代理的对象的资源,但是耦合紧密。
动态代理相对于静态代理来说,减少了代码的重复。
以上即实现代理的四种方式,说的不是很详细,如果有不对的地方,请指正。