超级好懂的设计模式——代理模式

精心整理了设计模式——代理模式,并配图加代码,方便理解,实属不易,但是难免不了存在纰漏,感谢大家的指正与理解!觉的写的不错的小伙伴儿,一键三连支持一下,后期会有持续更新!!抱拳了罒ω罒

代理模式简介

  • 代理模式:为其他对象提供一种代理以控制对这个对象的访问。通过代理就是不改变原有业务的基础上,对业务方法进行增强。
  • 代理模式分为静态代理和动态代理;实现动态代理的方式有JDK 动态代理和CGLIB 动态代理
  • 代码步骤:
    • 接口;
    • 真实角色(被代理角色);
    • 代理角色;
    • 客户(客户端访问代理角色);

1. 静态代理

我们以租客租客租房子为例,租客通过中介租住房东的房子,并从中获取中介费用。

Rent接口:抽象接口

//租房接口
public interface Rent {
    public void rent();
}

Host 类:房东(被代理对象)要出租房子

class Host implements Rent{

    @Override
    public void rent() {
        System.out.println("房东要出租房子!!!");
    }
}

Proxy 类:中介(代理对象)替房东完成租房

class Proxy implements Rent{
    private Host host;

    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        System.out.println("中介带领客户看房");//对租房进行增强
        host.rent();//进行租房
        System.out.println("中介收中介费");//对租房再进行增强
    }
}

演示:

class client{
    public static void main(String[] args) {
        Host host = new Host();//房东租房
        Proxy proxy = new Proxy(host);//中介代替房东租房
        proxy.rent(); //中介带领客户看房
					  //房东要出租房子!!!
					  //中介收中介费
        
    }
}

存在的问题:代理类手动创建,如果需要代理的对象多了,那么代理类也越来越多。因此动态代理应运而生。

2. 动态代理——JDK 动态代理

  如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP ,核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法来调用目标类中的代码; Proxy利用 InvocationHandler创建的实例, 生成目标类的代理对象。
  JDK 动态代理本质上是 实现了被代理对象的接口。
  JDK动态生成的代理类已经继承了Proxy类, 由于java的单继承,所以只能靠实现被代理类的接口的形式,故JDK的动态代理必须有接口。

以在开发过程中实际应用为例说明。
UserService接口:定义查询用户的方法;

interface UserService{
    //查询方法
    public void select();
}

UserServiceImpl 类:UserService接口的实现;

class UserServiceImpl implements UserService{
    @Override
    public void select() {
        System.out.println("查询一个用户");
    }
}

JDKProxyInvocationHandler 类:JDK动态类的实现

class JDKProxyInvocationHandler implements InvocationHandler{
	//真实对象,即被代理对象
    private Object target;

    public JDKProxyInvocationHandler(Object target) {
        this.target = target;
    }
    //通过Proxy类,创建代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
        							  target.getClass().getInterfaces(), 
        							  this);
    }

	//invoke方法,代理对象执行的增强的方法。
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) 
    throws Throwable {
        System.out.println("查询用户之前进行检验用户是否登录!");
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}

演示:

class client{
    public static void main(String[] args) {
    	//真实对象,被代理对象
        UserServiceImpl service = new UserServiceImpl();
        //代理对象的创建
        JDKProxyInvocationHandler handler = new JDKProxyInvocationHandler(service);
        UserService proxy = (UserService) handler.getProxy();
        //代理对象的增强方法
        proxy.select();
        
		//输出
		//查询用户之前进行检验用户是否登录!
		//查询一个用户

    }
}

2. 动态代理——CGLIB 动态代理

如果目标对象没有实现接口,必须采用CGLIB,其主要是对指定的类生成一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成final。CGLIB 动态代理需要引入第三方的 jar 包。

以在开发过程中实际应用为例说明。UserService接口和UserServiceImpl 类是不变的。只需将代理类更改为CGLIB代理即可。

public class CglibProxyFactory implements MethodInterceptor {

    // 目标对象(被代理对象)
    private Object target;
    
    public CglibProxyFactory(Object target) {
        this.target = target;
    }
    // 创建代理对象
    public Object createProxy() {
        // 1.创建Enhancer
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(target.getClass());   
        enhancer.setCallback(this);

        return enhancer.create();
    }
	// 真正执行代理增强的方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, 
    MethodProxy methodProxy) throws Throwable {
    
        System.out.println("查询用户之前进行检验用户是否登录!");
        Object invoke = method.invoke(target, objects);
        
        return invoke;
    }

    public static void main(String[] args) {
        // 1.创建对象
        UserServiceImpl service = new UserServiceImpl();
        // 2.创建代理对象
        CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(service );
        UserService userServiceProxy = (UserService) 
        cglibProxyFactory.createProxy();
        //代理对象的增强方法
        userServiceProxy.select();
        //输出
		//查询用户之前进行检验用户是否登录!
		//查询一个用户
    }
}

学习视频与参考文章:
https://www.bilibili.com/video/BV1mc411h719?p=11
https://csp1999.blog.csdn.net/article/details/117672843

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

corlor_龙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值