23种设计模式之---代理模式(Proxy Pattern)

代理模式:结构型设计模式,代理模式(Proxy)是为其他对象提供一种代理以控制对这个对象的访问.

Java的代理模式
代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

23种设计模式之---代理模式(Proxy Pattern)_第1张图片

1.静态代理
    静态代理是代理模式的实现方式之一,是相对于动态代理而言的。所谓静态代理是指,在程序运行前,由程序员创建或特定工具自动生成源代码并对其编译生成.class文件。
    静态代理的实现只需要三步:首先,定义业务接口;其次,实现业务接口;然后,定义代理类并实现业务接口;最后便可通过客户端进行调用。

package Proxy.Static;
public interface DAOInterface {
    public void add();
    public void delete();
    public void update();
    public void query();
}

package Proxy.Static;
public class UserDao implements DAOInterface{
    @Override
    public void add() {
        System.out.println("在目标对象中执行add");
    }
    @Override
    public void delete() {
        System.out.println("在目标对象中执行delete");
    }
    @Override
    public void update() {
        System.out.println("在目标对象中执行update");
    }
    @Override
    public void query() {
        System.out.println("在目标对象中执行query");
    }
}

package Proxy.Static;
/**
 * 代理对象
 * @author ctk
 *
 */
public class UserDaoProxy implements DAOInterface{
    UserDao userDao = null;
    public UserDaoProxy(UserDao userDao){
        this.userDao = userDao;
    }
    @Override
    public void add() {
        userDao.add();
        System.out.println("记录日志add");
    }
    @Override
    public void delete() {
        userDao.delete();
        System.out.println("记录日志delete");
    }
    @Override
    public void update() {
        userDao.update();
        System.out.println("记录日志update");
    }
    @Override
    public void query() {
        userDao.query();
        System.out.println("记录日志query");
    }
}

静态代理就是写死了在代理对象中执行这个方法前后执行添加功能的形式,每次要在接口中添加一个新方法,则需要在目标对象中实现这个方法,并且在代理对象中实现相应的代理方法,幸而Java有独特的反射技术,可以实现动态代理。

2.JDK动态代理
    特点:只能对实现了接口的类生产代理,不能针对类
    JDK动态代理的一般步骤如下:
        创建被代理的接口和类;
        实现InvocationHandler接口,对目标接口中声明的所有方法进行统一处理;
        调用Proxy的静态方法,创建代理类并生成相应的代理对象;
        使用代理。

package Proxy.jdkProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test {
    public static void main(String[] args) {
        final DAOInterface userDao = new UserDao();
        DAOInterface proxy = (DAOInterface) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces()
                , new InvocationHandler() {
                    //回调方法 拦截到目标对象的时候执行
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("在 代理对象 中拦截到:"+method.getName());
                        Object o = method.invoke(userDao, args);//调用拦截到的方法
                        return o;
                    }
                });
        proxy.delete();
    }
}

3.cglib动态代理
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
CGLIB是一个强大的高性能的代码生成包。被广泛的许多AOP框架使用,如Spring的AOP和dynaop,为他们提供方法的interceptor(拦截),最流行的是OR Mapping工具Hibernate也是使用CGLIB来代理单端的single-ended(多对一和一对一)关联(对集合的延迟抓取是采用其他机制实现)。EsayMock和jMock是通过模仿(moke)对象来测试java代码的包。他们都是通过使用CGLIB来为那些没有接口的类创建模仿(moke)对象。
需要先导入两个jar包: asm-5.1.jar 和  cglib-3.2.4.jar

package Proxy.Cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * cglib代理 要求类不能使final 代理对象继承目标对象
 * 
 * @author ctk
 *
 */
public class Test {
    public static void main(String[] args) {
        final UserDao target = new UserDao();
        Enhancer en = new Enhancer();
        //设置代理对象的父类
        en.setSuperclass(target.getClass());
        //设置回调
        en.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
                System.out.println("在 代理对象 中拦截到 "+arg1.getName());
                Object obj = arg1.invoke(target, arg2);
                return obj;
            }
        });
        UserDao proxy = (UserDao) en.create();
        proxy.add();
    }
}

Cglib实现代理的方式是和目标对象使用同一个父类,无论是继承还是实现接口,都是为了代理对象能直接调用目标对象的方法。

 

 

 

 

 

你可能感兴趣的:(设计模式)