代理模式

1. 代理模式介绍

  • 代理模式:为其他对象提供一种代理以控制对这个对象的访问,通过代理对象访问目标对象,这样做的好处是可以在目标对象实现的基础上,进行额外功能的增加,实现对目标对象的拓展!

  • 主要解决:比如对象创建开销很大,或者需要安全控制的对象,或者需要进程外的访问,直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

  • 代理形式:主要分为三种模式:静态代理、动态代理、Cglib代理(特殊的动态代理)。


2. 静态代理

在这里插入图片描述

  1. 代理对象Proxy和目标对象都要实现同一个接口或类

  2. 代理对象内部聚合一个目标对象,客户端调用相同的方法就能完成至少同样的功能!

interface TeacherDao {
    public void teach();
}
class TeacherDaoImpl implements TeacherDao{
    @Override
    public void teach() {
        System.out.println("上课ing");
    }
}
class TeacherDaoImplProxy implements TeacherDao{
    private TeacherDao target;

    public TeacherDaoImplProxy(TeacherDao target) {
        this.target = target;
    }

    @Override
    public void teach() {
        System.out.println("添加功能拓展、安全检查、进行事务...");      //对原功能进行拓展
        target.teach();             //完成原来的核心功能
        System.out.println("结束!");
    }
}
public class Demo {

    public static void main(String[] args) {
        TeacherDao teacherDao = new TeacherDaoImpl();
        TeacherDaoImplProxy teacherDaoImplProxy = new TeacherDaoImplProxy(teacherDao);
        teacherDaoImplProxy.teach();
    }
}

优点:不在修改原对象的情况下能够进行功能增强、安全检查等一些机制。

缺点:需要与目标对象实现同一个接口、类;一旦进行增加方法,目标对象与代理对象都需要进行维护!


3. 动态代理

动态代理:也叫JDK代理、接口代理;为了解决静态代理的的缺点:代理类需要实现与目标类(委托类)都需要实现同一个接口,使用Proxy类 和 InvocationHandler接口反射实现动态代理。

Proxy类的作用:通过传入一个目标类(委托类)生成代理对象。

InvocationHandler接口的作用:充当代理类 与 目标类之间的桥梁。

在这里插入图片描述

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

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

class TeacherDaoImplProxy implements InvocationHandler {
    private Object target;

    public TeacherDaoImplProxy() {}

    //获得代理对象
    public Object getProxy(Object target){
        this.target = target;
        /*
            1. 获取目标类的类加载器
            2. 获取目标类的接口方法
            3. 传入连接桥梁(本类实现了InvocationHandler接口,传入本类即可)
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    //执行代理方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /*
            1. target为目标对象
            2. args是目标对象委托执行方法中的参数
            3. result是执行结果(方法的返回值)
         */
        methodLog(method.getName());                //功能增强!
        Object result = method.invoke(target, args);
        return result;
    }
    
    public void methodLog(String name){
        System.out.println(name + "方法的日志...");
    }
}
public class Demo {

    public static void main(String[] args) {
        TeacherDao teacherDao = new TeacherDaoImpl();
        TeacherDaoImplProxy implProxy = new TeacherDaoImplProxy();
        TeacherDao proxy = (TeacherDao)implProxy.getProxy(teacherDao);
        proxy.teach();
    }
}

动态代理:

  • 优点:不用再与目标类实现同一个接口,灵活性大大增强;正因为如此动态代理类可以作为一个固定的模板进行使用,内部不在聚合一个类型的目标对象,直接聚合Object类型。可以动态代理一切目标接口、从而达到对代理接口实现类功能的增强!

  • 缺点:虽然不用再实现与目标类相同的接口,但是还是需要实现InvocationHandler接口辅助处理


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值