设计模式—代理模式

代理模式

参考博客:

Java的三种代理模式

Java-代理模式的理解

设计模式—代理模式

定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。

假设你的同事写了一个登录业务实现类,同事离职了,你接了他的锅,现在PM让你在登录功能的基础上添加登录日志。你有两个选择,一是修改同事的已经写好的代码,二是写一个代理,在不改动代码的基础上,增加日志功能。

编写代理的好处是,不用修改别人的代码,符合软件设计的开闭原则。

代理模式分为:

  • 静态代理
  • 动态代理

静态代理

// 服务接口 唱歌
public interface Singing {
    void singSong();
}

// 服务实现类 明星类 会唱歌
public class Star implements Singing {

    @Override
    void singSong(){
        system.out.printf("我是明星我在唱歌");
    }
    
}

// 代理类 明星代理 也可以唱歌
public class StarProxy implements Singing {
    private Say say;
    
    // 注入他代理的明星
    public StarProxy(fianl Say say){
        this.say = say;
    }
    
    @Override
    void singSong(){
        // do something before singSong
        system.out.printf("代理人在卖门票");
        // 代理让明星唱歌,他可以在明星唱歌前,唱歌后做其他业务
        say.singSong();
        system.out.printf("代理人在...");
        // do something after singSong
    }
}

// 测试类
public class ProxyTest {
    public static void main(String[] args) {
        Star star = new Star();
        
        StarProxy proxy = new StarProxy(star);
        proxy.singSong();
    }
}

可以看到静态代理都有以下特点:

  • 业务类(明星类)和 代理类都实现了同一个接口
  • 最终由代理类执行业务类方法,并由代理类扩展业务

动态代理

在java中动态代理比较常见的实现有基于jdk的实现和基于cglib的实现。
所谓的动态顾名思义就是,不用手动编写代理类,实现代理功能。

利用jdk反射机制实现动态代理

利用反射机制实现代理原理是一样的,只是在代码运行到时候自动新建代理类。目标对象必须实现接口才能使用jdk代理。

// java.lang.reflect.Proxy 类 获取代理实例工厂方法
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
  • ClassLoader loader :目标对象类加载器
  • Class<?>[] interfaces:目标类的接口
  • InvocationHandler h:目标类的句柄
// 代理工厂
public class ProxyFactory{

    //维护一个目标对象
    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }

   //给目标对象生成代理对象
    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 {
                        // 可以根据method的name来指定特定的方法代理
                        System.out.println("开始事务2");
                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("提交事务2");
                        return returnValue;
                    }
                }
        );
    }

}
利用cglib实现动态代理

cglib实现代理的原理是通过生成目标子类来实现代理的。所以,要求目标类不能是final类,代理的方法也不能是final/static修饰的方法。

// 代理工厂
public class ProxyFactory implements MethodInterceptor{
    //维护目标对象
    private Object target;

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

    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();

    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始事务...");

        //执行目标对象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事务...");

        return returnValue;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值