代理模式(静态,jdk动态代理,cglib动态代理)

目录

1.核心本质

2.静态代理

2.1 数字藏品举例

2.1.1 售卖接口

2.1.2 数字藏品所有者

2.1.3 数字平台售卖

2.1.4 测试类

2.2 CRUD例子

2.2.1 controller层

2.2.2 service 接口和实现

2.2.3 mapper 接口和实现

2.2.4 mapper代理类

2.2.5 测试类

3.动态代理

3.1 动态代理的分类

3.2 动态代理的优点

3.3 藏品的动态代理类

3.3.1 动态代理类

3.3.2 测试类

3.4 mapper动态代理类(万能代理)

3.4.1 万能代理类

3.4.2 测试类

4.动态代理(cglib)

4.1 拦截器

4.2 客户端

5.JDK和CGLIB的区别



1.核心本质

在不改动原有代码的情况下,进行逻辑的增加。

2.静态代理

每个都需要手动生成一个代理类,繁琐,耦合度高(动态代理优化)

2.1 数字藏品举例

2.1.1 售卖接口

/**
 * 售卖
 */
public interface Sale {

  void digitalSale();
}

2.1.2 数字藏品所有者

/**
 * 代表数字藏品主人
 */
public class DigitalcCllectiblesMaster implements Sale{
    @Override
    public void digitalSale() {
          System.out.println("数字藏品销售");
    }
}

2.1.3 数字平台售卖

/**
 * 代理平台
 */
public class ProxyPlatform implements Sale{
    private DigitalcCllectiblesMaster master;
    public ProxyPlatform(){

    }
    public ProxyPlatform(DigitalcCllectiblesMaster master) {
        this.master = master;
    }

    @Override
    public void digitalSale() {
        System.out.println("代理平台销售");
        master.digitalSale();
    }

    public void digitalSaleMore(){
        System.out.println("代理平台查看更多样式");
    }
    
    public void pay(){
        System.out.println("代理平台支付");
    }
}

2.1.4 测试类

public class Test {
    public static void main(String[] args) {
        //最开始不用平台代理,直接1对1售卖
        DigitalcCllectiblesMaster digitalcCllectiblesMaster = new DigitalcCllectiblesMaster();
        digitalcCllectiblesMaster.digitalSale();
        System.out.println("------------------------------------");
        //通过平台代理
        DigitalcCllectiblesMaster digitalcCllectiblesMaster1 = new DigitalcCllectiblesMaster();
        ProxyPlatform proxyPlatform = new ProxyPlatform(digitalcCllectiblesMaster1);
        proxyPlatform.digitalSale();
        //代理可以在不修改代码的情况下,增加一些额外的功能  此处体现就是 原来的1对1售卖,现在变成了平台售卖 平台可以收取手续费 可以选购其他的 也就是附属操作
        proxyPlatform.pay();
        proxyPlatform.digitalSaleMore();
    }
}

2.2 CRUD例子

2.2.1 controller层

/**
 * 控制层调用Service层
 */
public class CrudController {
    private CrudService crudService;

    public CrudController(CrudService crudService) {
        this.crudService = crudService;
    }

    public void add() {
        System.out.println("controller新增");
        crudService.add();
    }

    public void update() {
        System.out.println("controller修改");
        crudService.update();
    }

    public void delete() {
        System.out.println("controller删除");
        crudService.delete();
    }

    public void select() {
        System.out.println("controller查询");
        crudService.select();
    }
}

2.2.2 service 接口和实现

public interface CrudService {
    void add();
    void delete();
    void update();
    void select();
}


/**
 * 我们需要在数据库执行前 查看数据打印情况 不使用代理需要改原有代码 并且如果有多个方法 需要增加很多代码
 * 我们可以使用代理类解决
 */
public class CrudServiceImpl implements CrudService{

    private CrudMapperImplProxy crudMapperImplProxy;

    public CrudServiceImpl(CrudMapperImplProxy crudMapperImplProxy) {
        this.crudMapperImplProxy = crudMapperImplProxy;
    }

    @Override
    public void add() {
        crudMapperImplProxy.add();
    }

    @Override
    public void delete() {
        crudMapperImplProxy.delete();
    }

    @Override
    public void update() {
        crudMapperImplProxy.update();
    }

    @Override
    public void select() {
        crudMapperImplProxy.add();
    }
}

2.2.3 mapper 接口和实现

public interface CrudMapper {
    void add();
    void delete();
    void update();
    void select();
}


public class CrudMapperImpl implements CrudMapper{
    @Override
    public void add() {
        System.out.println("添加数据");
    }

    @Override
    public void delete() {
        System.out.println("删除数据");
    }

    @Override
    public void update() {
        System.out.println("更新数据");
    }

    @Override
    public void select() {
        System.out.println("查询数据");
    }
}

2.2.4 mapper代理类

public class CrudMapperImplProxy implements CrudMapper{
    private CrudMapperImpl crudMapperImpl;

    public CrudMapperImplProxy(CrudMapperImpl crudMapperImpl) {
        this.crudMapperImpl = crudMapperImpl;
    }

    @Override
    public void add() {
        log("add方法执行前");
        crudMapperImpl.add();
    }

    @Override
    public void delete() {
        log("delete方法执行前");
        crudMapperImpl.delete();
    }

    @Override
    public void update() {
        log("update方法执行前");
        crudMapperImpl.update();
    }

    @Override
    public void select() {
        log("select方法执行前");
        crudMapperImpl.select();
    }

    public void log(String msg){
        System.out.println(msg+"执行数据为===");
    }
}

2.2.5 测试类

public class Test {
    public static void main(String[] args) {
        CrudController crudController = new CrudController(new CrudServiceImpl(new CrudMapperImplProxy(new CrudMapperImpl())));
        crudController.add();
    }
}

3.动态代理

3.1 动态代理的分类

1.jdk动态代理(举例为jdk)

2.cglib动态代理

3.基于字节码的动态代理:javasist

3.2 动态代理的优点

  减少重复代码: 动态代理可以在运行时生成代理类,从而避免编写大量重复的代理类代码。这样可以减少代码量,提高代码的可维护性和可读性。

  统一处理逻辑: 可以在代理类中统一处理额外的逻辑,例如日志记录、性能监控、事务管理等。这些逻辑可以集中在代理类中实现,而不需要分散到多个实际的业务类中去。

  耦合: 动态代理可以将实际的业务逻辑和横切关注点(cross-cutting concerns)分离开来。业务类专注于核心业务逻辑,而代理类则处理通用的横切关注点,从而实现了高内聚、低耦合的设计。

  灵活性: 动态代理可以根据需要动态创建代理对象,不需要预先知道所有的被代理类。这种灵活性使得动态代理适用于各种不同的场景和需求。

  扩展性: 由于动态代理可以通过编程的方式生成代理类,因此可以根据实际需求定制不同的代理类。这种灵活性和扩展性使得动态代理在软件设计中具有重要的地位和作用。

3.3 藏品的动态代理类

使用静态代理的固定类

3.3.1 动态代理类

public class ProxyInvocationHandle implements InvocationHandler {
    //被代理的接口
    private Sale sale;

    public void setSale(Sale sale){
        this.sale=sale;
    }
    //生成代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),sale.getClass().getInterfaces(),this);
    }
    //处理代理实例
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(sale, args);
        return invoke;
    }
}

3.3.2 测试类

public class Test {
    public static void main(String[] args) {
        //真实角色
        DigitalcCllectiblesMaster digitalcCllectiblesMaster = new DigitalcCllectiblesMaster();
        //代理过程,处理程序
        ProxyInvocationHandle proxyInvocationHandle = new ProxyInvocationHandle();
        proxyInvocationHandle.setSale(digitalcCllectiblesMaster);
        //代理对象
        Sale sale = (Sale) proxyInvocationHandle.getProxy();
        sale.digitalSale();

    }
}

3.4 mapper动态代理类(万能代理)

3.4.1 万能代理类

public class ProxyInvocationHandler implements InvocationHandler {
    private Object object;

    public void setObject(Object o){
        this.object=o;
    }

    public Object getProxyObject(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        beforeLog(method.getName());
        Object invoke = method.invoke(object, args);
        afterLog(method.getName());
        return invoke;
    }

    public void beforeLog(String s){
        System.out.println(s+"sql开始执行"+new Date());
    }
    public void afterLog(String s){
        System.out.println(s+"sql开始执行"+new Date());
    }
}

3.4.2 测试类

public class Test {
    public static void main(String[] args) {
        CrudMapperImpl crudMapper = new CrudMapperImpl();

        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        proxyInvocationHandler.setObject(crudMapper);

        CrudMapper crudMapper1 = (CrudMapper) proxyInvocationHandler.getProxyObject();
        crudMapper1.update();
    }
}

4.动态代理(cglib)

使用静态代理的固定类

4.1 拦截器

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
 * 需要cglib依赖 自己手动添加
 */
import java.lang.reflect.Method;
import java.util.Date;

public class CglibInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        beforeLog();
        Object o1 = methodProxy.invokeSuper(o, objects);
        afterLog();
        return o1;
    }

    public void beforeLog(){
        System.out.println("sql开始执行"+new Date());
    }
    public void afterLog(){
        System.out.println("sql开始执行"+new Date());
    }
}

4.2 客户端

import net.sf.cglib.proxy.Enhancer;
import shejimoshi.structural.a_proxy.dynamicProxy.demo02.CrudMapperImpl;

/**
 * 需要cglib依赖 自己手动添加
 */
public class Test {
    public static void main(String[] args) {
        CglibInterceptor cglibInterceptor = new CglibInterceptor();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(CrudMapperImpl.class);
        enhancer.setCallback(cglibInterceptor);
        CrudMapper crudMapper = (CrudMapper) enhancer.create();
        crudMapper.add();
    }
}

5.JDK和CGLIB的区别

代理类型

实现机制

回调方式

使用场景

效率

JDK

通过实现接口,通过反射机制获取接口里的方法,实现InvocationHandler接口,实现方法拦截,自定义Proxy.newProxyInstance()方法,以及invoke方法

调用invoke方法,代理类内部如果自定了proxy可以直接调用

目标类有实现接口

1.8高于cgilb

CGLIB

通过继承去实现,代理方法实现MethodsInterceptor调用父类的目标方法,在intercept方法内部自定义增强方法

调用intercept方法

没有被final修饰的类

第一次调用慢,因为要生成字节码,多次调用效率高

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值