JAVA设计模式(代理模式)

代理模式:为对象提供一个替身,以控制这个对象的访问,即通过代理对象访问目标对象。
这样的好处是:可以在目标对象实现的基础上,增强额外的功能操作。

代理模式有三种:静态代理、动态代理和cglib代理

静态代理:
静态代理在使用的时候需要定义接口或者父类,被代理对象和代理对象一起实现相同的接口和继承相同的父类。

案例:

//接口
public interface ITeacherDao {
    void teach();
}
//被代理对象
public class TeacherDao implements ITeacherDao {
    @Override
    public void teach() {
        System.out.println("上课");
    }
}
//代理对象
public class TeachProxy implements ITeacherDao {
    private ITeacherDao iTeacherDao;

    public TeachProxy(ITeacherDao iTeacherDao) {
        this.iTeacherDao = iTeacherDao;
    }

    @Override
    public void teach() {
        System.out.println("开始代理");
        iTeacherDao.teach();
        System.out.println("结束代理");
    }
}
//客户端调用
public class Client {
    public static void main(String[] args) {
        TeachProxy teachProxy=new TeachProxy(new TeacherDao());
        teachProxy.teach();
    }
}

类图
在这里插入图片描述
静态代理的缺点是代理类和委托类使用了相同的接口,如果接口增加了一个方法,那么代理类和委托类都要同时实现,维护麻烦。
还有一个缺点就是一个代理类只能代理一个类,如果需要代理其他类必须创建新的代理类。如果要为多个类都提供相同的增强,那么静态代理就无法胜任了。

动态代理
不需要实现接口,但是目标对象要实现接口。代理对象的生成是利用JDK的API,动态的在内存中构建代理对象。

public interface ITeacherDao {
    void teach();
}
public class TeacherDao implements ITeacherDao {
    @Override
    public void teach() {
        System.out.println("上课");
    }
}

在这里插入图片描述

public class ProxyFactory {
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    /*
        public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
         1、ClassLoader loader:指定当前目标使用的类加载器
         2、Class<?>[] interfaces:目标对象的接口类型,使用泛型来确认类型
         3、InvocationHandler h:对象处理,执行目标对象的方法时,会触发事件处理器方法,会把当前目标方法作为参数传入

     */
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("JDK代理开始");
                        Object returnVal = method.invoke(target, args);
                        System.out.println("JDK代理结束");
                        return returnVal;
                    }
                }
        );
    }
}

cglib代理
cglib代理的目标对象只是一个单独的对象,没有使用任何接口。

代码实现
首先在maven中引入cglib的坐标

    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.2.4</version>
    </dependency>

目标类

public class TeacherDao {
    public void teach(){
        System.out.println("上课(cglib)");
    }
}

代理类,主要有获取代理对象的方法和需要重写intercept方法,intercept方法的内容是对目标方法进行增强。

public class ProxyFactory implements MethodInterceptor {
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }
    //返回代理对象
    public Object getProxyInstance(){
        //1、创建工具类
        Enhancer enhancer=new Enhancer();
        //2、设置父类
        enhancer.setSuperclass(target.getClass());
        //3、设置回调函数
        enhancer.setCallback(this);
        //4、创建子类对象即代理对象
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib代理开始");
        method.invoke(target,objects);
        System.out.println("cglib代理结束");
        return null;
    }

客户端调用

public class Client {
    public static void main(String[] args) {
        TeacherDao teacherDao=new TeacherDao();
        ProxyFactory proxyFactory=new ProxyFactory(teacherDao);
        //获取代理对象
        TeacherDao proxyInstance= (TeacherDao) proxyFactory.getProxyInstance();
        //执行代理对象的方法,将触发intercept
        proxyInstance.teach();

    }
}
发布了56 篇原创文章 · 获赞 3 · 访问量 1632

猜你喜欢

转载自blog.csdn.net/qq_20786911/article/details/103501858
今日推荐