代理模式

来源:互联网 发布:手机淘宝抢拍技巧 编辑:程序博客网 时间:2024/06/16 11:29

当客户端需要调用某个对象时,客户端其实并不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可以返回该对象的代理(Proxy)。

在这种设计方式,系统会为某个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个Java对象代表另一个Java对象来采取行动。在某些情况下,客户端代码不想或者不能够直接调用被调用者,代理对象可以在客户和目标对象之间充当中介的角色。

普通代理示例

1.定义接口

public interface UserService {    void add();    void remove();}

2.实际对象

public class UserServiceImpl implements UserService{    public void add() {        System.out.println("-----------add--------------");    }    public void remove() {        System.out.println("-----------remove-------------");    }}

3.代理对象

package com.tony.proxy.common;import com.tony.proxy.jdk.UserService;public class UserServiceProxy implements UserService{    private UserService userService;    public UserServiceProxy(UserService userService){        this.userService = userService;    }    public void add() {        LogUtil.logBefore();        userService.add();        LogUtil.logAfter();    }    public void remove() {        LogUtil.logBefore();        userService.remove();        LogUtil.logAfter();    }}

4.增强器

public class LogUtil {    public static void logBefore(){        System.out.println("before...");    }    public static void logAfter(){        System.out.println("after...");    }}

测试:

import com.tony.proxy.jdk.UserService;import com.tony.proxy.jdk.UserServiceImpl;public class ProxyTest {    public static void main(String[] args) {        UserService userService = new UserServiceImpl();        UserService userServiceProxy = new UserServiceProxy(userService);        userServiceProxy.add();        userServiceProxy.remove();    }}

结果:

before...-----------add--------------after...before...-----------remove-------------after...

这个例子中,为原有的对象方法增加了日志增强器功能,分别在实际对象方法的前后打印日志。

动态代理

JDK提供了动态代理的支持,通过在运行期间创建一个接口的实现类来完成对目标对象的代理。

示例:

1.实现InvocationHandler 接口

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class MyInvocationHandler implements InvocationHandler {    private Object target;    public MyInvocationHandler(Object target) {        super();        this.target = target;    }    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        //功能增强-调用实际对象方法前打印日志        LogUtil.logBefore();        Object result = method.invoke(target, args);        //功能增强-调用实际对象方法后打印日志        LogUtil.logAfter();        return result;    }    public Object getProxy() {        return Proxy.newProxyInstance(Thread.currentThread()                .getContextClassLoader(), target.getClass().getInterfaces(),                this);    }}

测试:

public class ProxyTest {    public static void main(String[] args) {        UserService userService = new UserServiceImpl();        MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);        UserService proxy = (UserService) invocationHandler.getProxy();        proxy.add();        proxy.remove();    }}

结果:

before...-----------add--------------after...before...-----------remove-------------after...

动态代理中,代理类是动态创建的,并且动态处理对所代理方法的调用。MyInvocationHandler 中的invoke方法将作为动态代理对象的所有方法的实现体,当程序调用动态生成的代理对象的指定方法时,实际上将变为执行MyInvocationHandler对象的invoke方法。

在整个创建的过程中,对于InvocationHandler的创建最为核心,在自定义的InvocationHandler中需要重写3个函数:
1.构造函数,将代理对象传入;
2.invoke方法,此方法中实现了AOP增强的所有逻辑;
3.getProxy方法,此方法千篇一律,但是必不可少。

0 0
原创粉丝点击