Java中的静态代理和动态代理

今天我们来聊一聊静态代理和动态代理

之所以写这个文章是因为我之前学代理的时候一头雾水,然后最近在学习Spring5框架的时候AOP的底层原理就是用到了动态代理,我就想着倒回去复习一下动态代理。我的学习方法是学不懂就先跳过,过了一段时间用到了再倒回来复习,我个人每次倒回来复习之前不懂的知识点,都会有一种开挂的感觉。我相信有些小伙伴也是和我一样。

话不多说,进入今天的主题。

静态代理(了解即可,使用较少)

静态代理的特点:代理类和被代理类在编译期间,就确定下来了。

静态代理需要三个要素。
① 接口
②实现接口的类 【俗称 被代理类
③创建一个类实现接口 【俗称 代理类

一、接口是规范,比如写dao层的时候,一般都会创建 一个接口UserDao 然后 再创建一个类 UserDaoImpl 去实现 UserDao接口

二、实现接口的类,这个就是很正常的 实现接口 然后重写抽象方法 这个没什么好说的。

三、创建一个类实现接口 为什么要创建呢?别管为什么! 反正就是要这样写

下面贴出代码讲解

创建一个接口 ClothFactory翻译过来也就是 衣服工厂
【接口中有一个抽象方法没什么好说的!!!】

interface ClothFactory{

    void produceCloth();

}

创建被代理类 NikeClothFactory翻译过来也就是耐克衣服工厂
【接口实现类,重写接口中的抽象方法也属于正常操作!!!】

//被代理类
class NikeClothFactory implements ClothFactory{

    @Override
    public void produceCloth() {
        System.out.println("Nike工厂生产一批运动服");
    }
}

创建代理类
【创建代理类,这里需要说一下】
1、创建的代理类需要实现,和被代理类相同的接口,也就是上方的接口。
2、也需要重写抽象方法
3、有一个 被代理类类型 的 成员变量 【用来调用方法,通过代理的构造方法进行赋值】

//代理类
class ProxyClothFactory implements ClothFactory{

    private ClothFactory factory;//用被代理类对象进行实例化

    public ProxyClothFactory(ClothFactory factory){
        this.factory = factory;
    }

    @Override
    public void produceCloth() {
        System.out.println("代理工厂做一些准备工作");

        factory.produceCloth();

        System.out.println("代理工厂做一些后续的收尾工作");

    }
}

接下来是测试类:
【先创建被代理类的对象,然后通过构造方法创建代理类对象,这时候,被代理类对象已经被赋值了,然后被代理类调用方法,方法里面 调用了被代理对象的方法】

public class StaticProxyTest {
    public static void main(String[] args) {
        //创建被代理类的对象
        ClothFactory nike = new NikeClothFactory();
        //创建代理类的对象
        ClothFactory proxyClothFactory = new ProxyClothFactory(nike);

        proxyClothFactory.produceCloth();

    }
}

动态代理(这个比较常用,需要学会)

动态代理,也就是不在编译时创建代理类,而是在运行时,自动创建代理类。从而实现动态代理的动态性。动态代理需要以下三个要素
①接口
②接口实现类
③代理类工厂 (用来创建代理类的工厂)
这两个都是正常的操作,没什么好说的。

下面通过代码进行讲解

接口 Human翻译过来也就是 人

interface Human{

    String getBelief();

    void eat(String food);

}

被代理类 SuperMan翻译过来也就是 超人

//被代理类
class SuperMan implements Human{


    @Override
    public String getBelief() {
        return "I believe I can fly!";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃" + food);
    }
}

代理类工厂
工厂类中有一个创建代理类对象的方法,参数是被代理类对象,返回的是被代理类对象。MyInvocationHandler是自定义的一个类,因为newProxyInstance()方法中的第三个参数需要一个实现InvocationHandler接口的类,bind()也是自定义的方法。

class ProxyFactory{
    //调用此方法,返回一个代理类的对象。解决问题一
    public static Object getProxyInstance(Object obj){//obj:被代理类的对象
        MyInvocationHandler handler = new MyInvocationHandler();

        handler.bind(obj);

        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
    }

}

MyInvocationHandler类
创建代理类对象的时候会自动调用本类中的 invoke()方法,bind()方法是为了给 被代理类类型 的 成员变量赋值,invoke()方法的
第一个参数是 代理类对象,
第二个参数是 代理类对象调用的方法,method.invoke()方法是反射的invoke()方法,
第三个参数是 方法的参数

class MyInvocationHandler implements InvocationHandler{

    private Object obj;//需要使用被代理类的对象进行赋值

    public void bind(Object obj){
        this.obj = obj;
    }

    //当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()
    //将被代理类要执行的方法a的功能就声明在invoke()中
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
        //obj:被代理类的对象
        Object returnValue = method.invoke(obj,args);
        
        //上述方法的返回值就作为当前类中的invoke()的返回值。
        return returnValue;

    }
}

测试类代码:

public class ProxyTest {

    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //proxyInstance:代理类的对象
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        //当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
        String belief = proxyInstance.getBelief();
        System.out.println(belief);
        proxyInstance.eat("四川麻辣烫");

        System.out.println("*****************************");

        NikeClothFactory nikeClothFactory = new NikeClothFactory();

        ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);

        proxyClothFactory.produceCloth();

    }
}

到这里,本篇文章就讲解结束,如果有看不懂的,可以去尚硅谷找java课程,代码来自尚硅谷宋红康,我个人也是康师傅的忠实粉丝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值