:: 首页 ::  :: 联系 :: 聚合  :: 管理

AOP基础:动态代理

Posted on 2009-11-07 21:27 codingliyi 阅读(253) 评论(0)  编辑  收藏 所属分类: Design Patterns

在了解动态代理之前,有必要先知道什么是静态代理。

1. 静态代理

在静态代理的实现中,代理对象与被代理对象都必须实现同一个借口,在代理对象中可以实现日志记录等相关服务,并在需要的时候在呼叫被代理对象。如此代理对象中就可以仅保留业务相关职责。

示例代码:

首先定义一个IHello接口:

1public interface IHello {
2        public void sayHello(String name);
3}
然后让实现业务逻辑的HelloSpeaker类实现IHello接口:
1public class HelloSpeaker implements IHello {
2    public void sayHello(String name) {
3            System.out.println("Hello, " + name);
4    }

5}
将日志记录功能放入代理对象中,代理对象同样也要实现IHello接口:
 1import java.util.logging.*;
 2
 3public class HelloSpeakerProxy implements IHello {
 4    
 5    private Logger logger = Logger.getLogger(this.getClass().getName());
 6    private IHello helloObject;
 7    
 8    public HelloSpeakerProxy(IHello hello){;
 9        this.helloObject = hello;
10    }

11    public void sayHello(String name) {
12        logger.log(Level.INFO, "before sayHello");
13        helloObject.sayHello(name);
14        logger.log(Level.INFO, "after sayHello");
15    }

16}
编写测试程序:
 1public class StaticProxyDemo {
 2    public static void main(String[] args) {
 3        HelloSpeakerProxy proxy = new HelloSpeakerProxy(new HelloSpeaker());
 4        proxy.sayHello("codingliyi");
 5    }

 6//    运行结果:
 7//    2009-11-7 21:21:55 SpringAOP.HelloSpeakerProxy sayHello
 8//    信息: before sayHello
 9//    Hello, codingliyi
10//    2009-11-7 21:21:55 SpringAOP.HelloSpeakerProxy sayHello
11//    信息: after sayHello
12}

静态代理缺陷:代理对象的一个接口只服务于一种类型的被代理对象。如果要代理的方法很多,静态代理就无法胜任。

2. 动态代理

JDK1.3之后加入了可协助开发动态代理功能的API,不必为特定对象与方法编写特定的代理对象。使用动态代理,可以使得一个处理者(Handler)服务于各个对象。

相关的接口和类有如下两个:

1.java.lang.reflect.InvocationHandler接口

该接口仅定义了一个方法:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable

其中,proxy指代理类,method是被代理的方法,args指方法的参数。

2.java.lang.reflect.Proxy;

该类最主要的方法:

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

其中,loader指被代理类的类加载器;interfaces指被代理类实现的接口,h指方法调用的处理程序。

动态代理的示例代码如下:

DynamicProxyHandler.java
 1public class DynamicProxyHandler implements InvocationHandler {
 2    private Object delegate;
 3    
 4    public DynamicProxyHandler(Object delegate){
 5        this.delegate = delegate;
 6    }

 7    
 8    public Object invoke(Object proxy, Method method, Object[] args)
 9            throws Throwable {
10        System.out.println("调用方法前");
11        Object result = method.invoke(delegate,args);
12        System.out.println("调用方法后");
13        return result;
14    }

15}
DynamicProxyDemo.java
 1public class DynamicProxyDemo {
 2    public static void main(String[] args) {
 3        HelloSpeaker speaker = new HelloSpeaker();
 4        IHello hello = (IHello)Proxy.newProxyInstance(speaker.getClass().getClassLoader(), speaker.getClass().getInterfaces(), new DynamicProxyHandler(speaker));
 5        hello.sayHello("codingliyi");
 6    }

 7//    运行结果:
 8//    调用方法前
 9//    Hello, codingliyi
10//    调用方法后
11}

动态代理的实战步骤:
a.    业务接口,一个Interface;
b.    实现业务接口的类,即被代理类;
c.    一个继承了java.lang.reflect.InvocationHandler的Handler类,里面维持了一个被代理对象的引用(Object类型),实现invoke()方法;
d.    使用Proxy.newProxyInstance()将Handler与被代理类关联,得到代理类,并强制转化为接口类型;
e.    调用该接口的方法。

只有注册用户登录后才能发表评论。


网站导航: