设计模式之代理模式

代理模式

代理模式(Proxy Pattern)为其他类提供代理控制对象访问,属于结构型模式,满足开闭原则。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

例子
  • 买火车票不一定去火车站买也可以去代售点买
  • 卖房子可以委托中介帮卖
  • 电脑桌面创建快捷方式
分类

代理模式分为静态代理,动态代理。
静态代理:程序员自己写的代理类
动态代理:分为Jdk和CJLB动态代理方式

静态代理

使用代理方式在执行order前后增加日志纪录操作

package com.mode.proxy;

public interface OrderService {

    public void order();
}
package com.mode.proxy;

public class Order implements OrderService{

    public void order(){
        System.out.println("订单操作------->start");
        System.out.println("订单操作------->end");
    }
}
package com.mode.proxy;

public class StaticProxy implements OrderService{

    private Order order;

    public StaticProxy(Order order){
        this.order = order;
    }

    @Override
    public void order() {
        System.out.println("日志记录开始---------->");
        this.order.order();
        System.out.println("日志记录结束---------->");
    }
}
package com.mode.proxy;

public class TestProxy {

    public static void main(String[] args) {
        new StaticProxy(new Order()).order();
    }
}

静态代理可以对接口进行增强,如上案例中对订单增加了日志处理,假如我们登陆、支付等操作都要日志处理不可能写很多这样的代理类,这时引入动态代理方式。

动态代理->Jdk动态代理

利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,
在调用具体方法前调用InvokeHandler来处理。
参数解析:
Object proxy--------->Jvm生成的被代理类的动态代理对象
Method method----->代理对象中的你要调用的方法
Object[] args--------->你调用代理对象传递的参数

@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
    }

Proxy.newProxyInstance参数解析
CLassLoader loader------->被代理对象的类加载器
Class<?> interfaces------->被代理类全部的接口
InvocationHandler h------->实现InvocationHandler接口的对象

newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

在invoke中日志处理。

package com.mode.proxy;

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

public class JdkOrderProxy implements InvocationHandler {

	//Object类型动态代理
    private Object obj;

    public Object newProxyInstance(Object object){
        this.obj=object;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("日志记录开始---------->"+args);
        Object invoke = method.invoke(obj, args);
        System.out.println("日志记录开始---------->");
        return invoke;
    }

    public static void main(String[] args) {
        JdkOrderProxy orderProxy = new JdkOrderProxy();
        Object newProxyInstance = orderProxy.newProxyInstance(new Order());
        OrderService orderService=(OrderService)newProxyInstance;
        orderService.order();
    }
}
动态代理->Cjlb动态代理

利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

package com.mode.proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CJlbProxy implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("日志记录开始---------->");
        Object invoke = methodProxy.invoke(o, objects);
        System.out.println("日志记录开始---------->");
        return invoke;
    }

    public static void main(String[] args) {
        //Enhancer为字节码增强器,很方便对类进行扩展
        Enhancer enhancer = new Enhancer();
        //传入被代理类
        enhancer.setSuperclass(Order.class);
        //传入实现MethodInterceptor接口对象
        enhancer.setCallback(new CJlbProxy());
        返回代理对象,是被代理类的子类
        Order order = (Order) enhancer.create();
        //调用
        order.order();
    }
}

如何选用

1、如果目标对象实现了接口,两种都可以用。
2、如果目标对象没有实现了接口,必须采用CGLIB库。

总结

1、JDK代理是不需要第三方库支持,只需要JDK环境就可以进行代理,使用条件:

  • 实现InvocationHandler

  • 使用Proxy.newProxyInstance产生代理对象

  • 被代理的对象必须要实现接口

2、CGLib必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值