Java设计模式-代理模式

设计模式(Design Pattern),其实就是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、提高代码的可靠性。分为三大类型,分别是:创建型模式、结构性模式、行为型模式。7大设计原则:开闭原则、接口隔离原则、合成复用原则、里氏替换原则、最少原则(迪米特法则)、单一职责原则、依赖倒置原则。具体的详细介绍大家自行百度,搜索。

代理模式的主要角色有三个:
抽象主题(Subject):定义了真实主题和代理主题的公共接口,使得在任何使用真实主题的地方都可以使用代理主题。
真实主题(RealSubject):实现了抽象主题的接口,定义了真实的业务逻辑,是代理主题所代表的真实对象。
代理主题(Proxy):也实现了抽象主题的接口,但是在调用真实主题的方法之前或之后,可以执行一些额外的操作,从而对真实主题进行控制或增强。

静态代理

抽象主题接口

/**
 * @version 1.0.0
 * @className: Subject
 * @description: 抽象主题接口
 * @author: zhangjunfa
 * @date: 2023/8/29 9:13
 */
public interface Subject {/**
     * 程序猿工作类
     */
    public void work();
}

真实的主题对象类

import lombok.extern.slf4j.Slf4j;import java.util.Date;/**
 * @version 1.0.0
 * @className: UserWork
 * @description: 程序猿工作类,也是真实的主题类。实现了 抽象主题接口
 * @author: zhangjunfa
 * @date: 2023/8/29 9:21
 */
@Slf4j
public class UserWork implements Subject {
    /**
     * 程序猿工作类,这是真实的业务逻辑
     */
    public void work() {
        log.info("我是一只《只会写Bug的程序猿》,我今天需要码字10W,date:{}", new Date());
    }
}

代理主题类

import lombok.extern.slf4j.Slf4j;/**
 * @version 1.0.0
 * @className: Proxy
 * @description: 代理主题类,实现了抽象主题接口
 * @author: zhangjunfa
 * @date: 2023/8/29 9:24
 */
@Slf4j
public class Proxy implements Subject {
    /**
     * 真实的主题对象类,程序猿工作
     */
    private UserWork userWork;/**
     * 构造器
     *
     * @param userWork
     */
    public Proxy(UserWork userWork) {
        this.userWork = userWork;
    }/**
     * 程序猿工作类
     */
    public void work() {
        log.info("在调用真实的主题类之前,把5W的码字工作分给 张三。。。。{}", new User(1L, "张三", "疯狂码字"));// <只会写Bug的程序猿> 在努力的工作。。。。。。。。。
        // 这个地方就是 真实的主题类,就是我这只程序猿。我要做的就是真实的业务逻辑。(就是码字10W)
        userWork.work();
​
        log.info("在调用真实的主题类之后,又把5W的码字工作分给 李四。。。。{}",new User(4L,"李四","疯狂码字"));
    }
}

测试

public class ApiTest {// ApiTest.
    @Test
    public void test() {
        // 真实的主题对象
        UserWork userWork = new UserWork();//  代理对象,并传入真实主题对象
        Proxy proxy = new Proxy(userWork);// 使用代理对象来调用抽象方法
        proxy.work();
    }/*
    代理对象在调用真实对象的方法之前和之后,都执行了一些额外的操作,
    从而对真实对象进行了增强或控制。
    本例中。我需要码字10W,在调用真实对象前。我把5W的码字工作交给
    了张三。调用之后又把5W的码字工作交给了李四。
    /手动滑稽的笑,我在偷懒。
     */
}

结果:
静态代理测试结果

Jdk动态代理

代理类

/**
 * @version 1.0.0
 * @className: JdkProxy
 * @description:  代理类
 * @author: zhangjunfa
 * @date: 2023/3/31 9:58
 */
@Slf4j
public class ProxyHandler<T> implements InvocationHandler {
    private final T target;public ProxyHandler(T target) {
        this.target = target;
    }public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
​
        log.info("代理前-----");
        Object result = method.invoke(target, args);
        log.info("代理后-----代理方法:{},参数:{}", method.getName(), args);
        return result;
    }
}

代理类工厂类

/**
 * @version 1.0.0
 * @className: JdkProxy
 * @description: 代理类工厂类
 * @author: zhangjunfa
 * @date: 2023/3/31 10:06
 */
public class ProxyFactory<T> {
    private T target;public ProxyFactory(T target) {
        this.target = target;
    }public T newInstance() {
        ProxyHandler<T> jdkProxyHandler = new ProxyHandler<T>(target);
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), jdkProxyHandler);
    }}

用户Service

/**
 * @version 1.0.0
 * @className: UserService
 * @description:
 * @author: zhangjunfa
 * @date: 2023/3/31 9:55
 */
public interface UserService {
    void addUser(String id,String name);Object getUserById(String id);
}

测试

@Test
public void test_Proxy() {
    ProxyFactory<UserService> factory = new ProxyFactory<UserService>(new UserServiceImpl());
    UserService userService = factory.newInstance();
    userService.addUser("1","Rosszhang");
    Object username = userService.getUserById("1");
    log.info("测试结果:{}", username);}

Jdk代理测试结果

Cglib动态代理

引入Cglib类库

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.12</version>
</dependency>

用户接口和实现类

import com.ross.mode.User;/**
 * @version 1.0.0
 * @className: UserService
 * @description: 用户操作接口
 * @author: zhangjunfa
 * @date: 2023/8/29 13:20
 */
public interface UserService {/**
     * 新增用户
     * @param user
     */
    void addUser(User user);
}/*********优美且自带华丽的分割线*******************/import com.ross.mode.User;
import lombok.extern.slf4j.Slf4j;/**
 * @version 1.0.0
 * @className: UserServiceImpl
 * @description: 用户操作接口实现类
 * @author: zhangjunfa
 * @date: 2023/8/29 13:28
 */
@Slf4j
public class UserServiceImpl implements UserService {
    /**
     * 新增用户
     *
     * @param user
     */
    @Override
    public void addUser(User user) {
        log.info("新增了一条用户数据:{}", user);
    }
}

开启事务控制

import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/**
 * @version 1.0.0
 * @className: Mapper
 * @description: 开启事务控制,个人理解:相当于需要代理的操作。。
 * @author: zhangjunfa
 * @date: 2023/8/29 13:36
 */
@Slf4j
public class MapperTransactional {
    public void before(Object o, Method method, Object[] args, MethodProxy methodProxy) {
        // 如果输出 o ,会卡
        log.info("开启事务操作。。。。。。方法:{},参数:{}", method.getName(), args);
    }public void after(Object o, Method method, Object[] args, MethodProxy methodProxy) {
        // 如果输出 o ,会卡
        log.info("关闭事务操作.......方法:{},参数:{}", method.getName(), args);
    }
}

代理类

import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/**
 * @version 1.0.0
 * @className: Proxy
 * @description: 代理类
 * @author: zhangjunfa
 * @date: 2023/8/29 13:22
 */
@Slf4j
public class ProxyInterceptor implements MethodInterceptor {
    /**
     * 目标对象
     */
    private UserService target;/**
     * 事务控制
     */
    private MapperTransactional transactional;/**
     * 构造器
     *
     * @param target
     */
    public ProxyInterceptor(UserService target, MapperTransactional transactional) {
        this.target = target;
        this.transactional = transactional;
    }@Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        transactional.before(o, method, args, methodProxy);
        Object result = method.invoke(target, args);
        transactional.after(o, method, args, methodProxy);
        return result;
    }//返回一个代理对象:  是 target 对象的代理对象
    public Object getProxyInstance() {
        //1. 创建一个工具类
        Enhancer enhancer = new Enhancer();
        //2. 设置父类
        enhancer.setSuperclass(target.getClass());
        //3. 设置回调函数
        enhancer.setCallback(this);
        //4. 创建子类对象,即代理对象
        return enhancer.create();
    }
}

测试

// ApiTest.
    @Test
    public void test_CGLIB() {
        //创建目标对象
        MapperTransactional trascation = new MapperTransactional();
        UserService target = new UserServiceImpl();//获取到代理对象,并且将目标对象传递给代理对象
        UserService userService = (UserService) new ProxyInterceptor(target, trascation).getProxyInstance();//执行代理对象的方法,触发 intecept 方法,从而实现 对目标对象的调用
        userService.addUser(new User(4L,"张三","疯狂的写BUG"));}

测试结果
Cglib代理测试结果
以上测试案例的代码集合:源码地址:项目名称:ross-proxy-03
测试案例源码地址

注意:以上代码都是个人的理解,如有不当之处,还望指正,共同进步。同时也希望大家能给我更通俗易懂的案例。来加深理解。/360度鞠躬致谢。

下面这个是我的个人公共号 只会写Bug的程序猿,大家可以关注一下。相互交流学习。
只会写Bug的程序猿的公众号
Ross zhang的博客
RossZhang的CSDN地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拈㕦一笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值