Spring(十三):设计模式——代理模式

Spring中AOP的底层原理就是动态代理模式,所以我们在这里对代理模式进行学习。

一、代理模式

1.什么是代理

代理,顾名思义,就是一个人代替另一个人去做他需要做的事情。代理是一种设计模式,具体实现就是一个类代替某个类去实现功能。

我们举一个例子:

我要租房子,我可以找房东直接租房子。同样我可以找中介来租房子,这个中介就是代理,它代理房东来做租赁房子的事情。

2.为什么需要代理模式呢?

我们的开发一般都是纵向开发,当有新的需求出现但又不想改变原有的业务逻辑时,就需要用到代理模式了,代理模式属于横向开发,我们只需要代理原来的业物逻辑并在代理类中添加新的功能即可。

二、静态代理

1.定义一个接口;

2.被代理类实现接口;

3.代理类引用被代理类,并且通过被代理类的方法实现接口。

我们以上图为例子,来进行一个静态代理的简单应用:

1.定义一个rental接口

package com.jms.demo01;
//租房接口
public interface rental {
    void doRental();
}

2.被代理类landlord实现接口

package com.jms.demo01;
//房东
public class landlord implements rental{
    @Override
    public void doRental() {
        System.out.println("房东要出租房子");
    }
}

3.代理类intermediary引用被代理类,并且通过被代理类的方法实现接口。

package com.jms.demo01;
//中介
public class intermediary implements rental{

    private landlord landlord;

    public intermediary(landlord landlord) {
        this.landlord = landlord;
    }
    @Override
    public void doRental() {
        landlord.doRental();
        seeHouse();
        writeContract();
    }

    public void seeHouse() {
        System.out.println("中介带你看房子");
    }

    public void writeContract() {
        System.out.println("中介和你签合同");
    }
}

同时代理类可以根据实际需求添加自己的方法。

4.测试一下

package com.jms.demo01;
//租客
public class Tenants {
    public static void main(String[] args) {
        landlord landlord = new landlord();
        intermediary intermediary = new intermediary(landlord);
        intermediary.doRental();
    }
}

 

 

三、动态代理

上面静态代理的缺陷很明显,一个代理类对应一个被代理类,当我们的被代理类数量相当庞大时,我们也要写出相应的数量的代理类才行,为了解决这个问题,我们就需要用到动态代理。

我们再以上面租房为例用动态代理实现。

1.接口还是上面的rental接口;

2.代理类landlord实现接口与静态代理相同;

3.动态代理没有代理类,而是通过java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy来实现

具体写法如下:

package com.jms.demo3;

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

public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    //处理代理实例并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        java.lang.Object result = method.invoke(target, args);
        seeHouse();
        writeContract();
        return result;
    }
}

这段代码适用于任何接口的动态代理,即拿即用。

我们在上面类中可以随意添加我们需要的方法,此处我将其修改如下:

package com.jms.demo3;

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

public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    //处理代理实例并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        java.lang.Object result = method.invoke(target, args);
        seeHouse();
        writeContract();
        return result;
    }

    public void seeHouse() {
        System.out.println("中介带你看房子");
    }

    public void writeContract() {
        System.out.println("中介和你签合同");
    }
}

4.具体的使用

public class Tenants {
    public static void main(String[] args) {
        //被代理类
        landlord landlord = new landlord();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        //设置动态代理的接口
        proxyInvocationHandler.setTarget(landlord);
        //获取接口
        rental rental = (rental) proxyInvocationHandler.getProxy();
        //执行具体操作
        rental.doRental();
    }
}

 

 

 

 

(本文仅作个人学习记录用,如有纰漏敬请指正)

 

posted @ 2022-09-27 18:52  谁知道水烫不烫  阅读(588)  评论(0编辑  收藏  举报