栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

设计模式之代理模式(Proxy)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式之代理模式(Proxy)

代理设计模式主要对方法前后实现增强

应用场景

1 打印日志
2 AOP底层通过代理模式封装
3 事务@Transactional 底层AOP
4 Mybatis中的mapper接口
5 全局捕获异常
6 Lcn、Seata、分表分库框架sharding-jdbc 代理数据源
7 自定义注解生效
8 Rpc远程调用技术(通过dubbo调用接口只会引入接口)

代理模式优缺点

优点:实现扩展功能、对方法实现增强、安全性、解决代码冗余提高代码复用机制
缺点:生成非常多的class文件(代理类)

代理模式的分类

静态代理与动态代理

代理模式实现的原理

代理模式主要包含三个角色,即抽象主题角色(Subject)、委托类角色(被代理角色,Proxied)以及代理类角色(Proxy),如图所示:

  • 抽象主题角色:可以是接口,也可以是抽象类;
  • 委托类(被代理类)角色:真实主题角色,业务逻辑的具体执行者;
  • 代理类角色:内部含有对真实对象的引用,负责对真实主题角色的调用,并在真实主题角色处理前后做预处理和后处理。

eg:买房 中介 卖房(被代理类) 

1.静态代理的实现方式

基于接口实现(Jdk动态代理)和继承模式(Cglib字节码)

1.1 基于接口方式

接口

public interface OrderService {
    String addOrder(String orderId, String orderName);
}

实现类

public class OrderServiceImpl implements OrderService {
    @Override
    public String addOrder(String orderId, String orderName) {
        System.out.println("OrderServiceImpl真实方法执行...");
        return orderId + "," + orderName;
    }
}

代理类

public class OrderServiceProxy implements OrderService {
    //被代理类
    private OrderServiceImpl orderServiceImpl;

    public OrderServiceProxy(OrderServiceImpl orderServiceImpl) {
        this.orderServiceImpl = orderServiceImpl;
    }

    @Override
    public String addOrder(String orderId, String orderName) {
        System.out.println("采用代理模式统一打印日志 orderId:" + orderId + ",orderName:" + orderName);
        return orderServiceImpl.addOrder(orderId, orderName);

    }
}

测试

public class Test {
    public static void main(String[] args) {
        OrderService orderServiceProxy = new OrderServiceProxy(new OrderServiceImpl());
        orderServiceProxy.addOrder("mayikt", "111");
    }
}
1.2 基于继承方式

接口

public interface OrderService {
    String addOrder(String orderId, String orderName);
}

实现类

public class OrderServiceImpl implements OrderService {
    @Override
    public String addOrder(String orderId, String orderName) {
        System.out.println("OrderServiceImpl真实方法执行...");
        return orderId + "," + orderName;
    }
}

代理类

public class OrderServiceProxy extends OrderServiceImpl {
    @Override
    public String addOrder(String orderId, String orderName) {
        System.out.println("采用代理模式统一打印日志 orderId:" + orderId + ",orderName:" + orderName);
        return super.addOrder(orderId, orderName);
    }
}

测试

public class Test {
    public static void main(String[] args) {
        OrderService orderServiceProxy = new OrderServiceProxy();
        orderServiceProxy.addOrder("mayikt", "111");
    }
}
2.动态代理的实现方式

jdk动态代理和cglib动态代理

2.1 JDK动态代理方式

接口

public interface OrderService {
    String addOrder(String orderId, String orderName);
}

实现类

public class OrderServiceImpl implements OrderService {
    @Override
    public String addOrder(String orderId, String orderName) {
        System.out.println("OrderServiceImpl真实方法执行...");
        return orderId + "," + orderName;
    }
}

事件处理器(用于动态生成代理类)

public class JdkInvocationHandler implements InvocationHandler {
    //目标对象(被代理类)
    private Object target;

    public JdkInvocationHandler(Object object) {
        this.target = object;
    }

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

        System.out.println("jdk动态代理执行开始>>>" + args[0]);
        // 执行目标方法 java反射执行目标方法
        Object result = method.invoke(target, args);
        System.out.println("jdk动态代理执行结束>>>" + args[0]);
        return result;
    }

    
    public  T getProxy() {
        // ClassLoader 读取代理类class文件
        // Class[] interfaces 基于该接口拼接代理类的源代码
        // InvocationHandler this
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}

测试

public class Test {
    public static void main(String[] args) {
        JdkInvocationHandler jdkInvocationHandler = new JdkInvocationHandler(new OrderServiceImpl());
        // 创建代理类
        OrderService proxy = jdkInvocationHandler.getProxy();
        proxy.addOrder("mayikt", "maplefire");
    }
}
2.2 Cglib动态代理方式

接口

public interface OrderService {
    String addOrder(String orderId, String orderName);
}

实现类

public class OrderServiceImpl implements OrderService {
    @Override
    public String addOrder(String orderId, String orderName) {
        System.out.println("OrderServiceImpl真实方法执行...");
        return orderId + "," + orderName;
    }
}

方法拦截器(用于动态生成代理类)

public class CglibMethodInterceptor implements MethodInterceptor {

    
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("cglib动态代理执行开始>>>");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("cglib动态代理执行结束>>>");
        return result;
    }
}

测试

public class Test {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        //设置即将生成的代理类的父类
        enhancer.setSuperclass(OrderServiceImpl.class);
        //设置回调方法
        enhancer.setCallback(new CglibMethodInterceptor());

        // 创建代理对象
        OrderServiceImpl orderServiceImpl= (OrderServiceImpl) enhancer.create();
        orderServiceImpl.addOrder("mayikt", "maplefire");
    }
}
3.Jdk与Cglib动态代理的区别 Jdk动态代理:基于实现接口的形式生成代理类对象;使用java反射机制调用目标方法
  • 需要拼接java源代码$proxy.java
  • 需要将java源代码编译为class文件
  • 采用类加载器读取class文件到程序中
  • 采用java的反射机制执行目标方法

反射机制:method.invoke(target, args);

Cglib动态代理:基于继承目标对象生成代理类对象;(ASM)字节码技术
  • 直接采用字节码技术生成class文件(无需编译过程)
  • 采用类加载器读取class文件到程序中
  • 采用FastClass机制调用到目标方法(比反射机制效率要高)

FastClass机制:memberService.add()
FastClass对目标对象中所有的方法生成一个索引的标记,直接根据索引调用到目标方法。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/929885.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号