静态代理于动态代理

标题静态代理与动态代理的区别

关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式–代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。话不多说,直接上代码

静态代理

首先我们建一个公共proxy接口类

package com.honizon.proxy;
public interface personProxy {
    //定义一个获取名字的方法
    String getName();
}

再建一个类去实现它,这个类就是需要被代理的类。

package com.honizon.proxy.impl;
import com.honizon.proxy.personProxy;
public class studentProxy implements personProxy {
    @Override
    public String getName() {
        System.out.println("张三");
        return "被代理类";
    }
}

接下就是关键代码,在创建一个类去实现personProxy,这样他就可做与studentProxy类一样的事情

package com.honizon.proxy.impl;

import com.honizon.proxy.personProxy;

public class teacherProxy implements personProxy {

   //定义一个被代理的类
    private studentProxy student;

    public teacherProxy(personProxy student) {
        this.student = (studentProxy)student;
    }

    //在teacherProxy类调用获取名字,并在之前叫老师好
    public String getName(){
        System.out.println("老师好");
        student.getName();
        return "代理类";
    }
}

最后建一个测试类proxyTest,看如何使用代理模式:

package com.honizon.proxy;

import com.honizon.proxy.impl.studentProxy;
import com.honizon.proxy.impl.teacherProxy;

public class proxyTest {


        public static void main(String[] args) {
        //创建一个被代理的对象
        personProxy student = new studentProxy();
        //创建一个与代理对象,并把需要代理的对象放进去
        personProxy teacher = new teacherProxy(student);
        //获取名字
        teacher.getName();
    }
}

执行我们来看效果
在这里插入图片描述

在获取名字之前还叫了老师好,这就是代理模式好处,在执行原有事情下,还能做些别的,代理模式最主要的就是有一个公共接口(personProxy),一个具体的类(studentProxy),一个代理类(teacherProxy),代理类持有具体类的实例,代为执行具体类实例方法。上面说到,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。这里的间接性就是指不直接调用实际对象的方法,那么我们在代理过程中就可以加上一些其他用途

动态代理

动态代理相对静态代理跟灵活,跟方便,静态代理每一个需要被代理的类都需要创建代理类来管理,而动态代理是基于InvocationHandler类来实现,并不需要创建那么多的代理类,静态代理的代理是在运行之前就编译好的,而动态代理是在运行程序根据指令生成的,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法

  • 代码

先定义公共接口类personProxy

package com.honizon.proxy;
public interface personProxy {

    String getName();

}

接下创建一个实体类实现InvocationHandler类,这个类中持有一个被代理对象的实例target。InvocationHandler中有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法。,并在里面利用反射调用获取名字的方法,在方法之前打印执行了什么方法。

package com.honizon.Dynamic;

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

public class personHandler<T> implements InvocationHandler {

    T tager;

    public personHandler(T tager) {
        this.tager = tager;
    }
     /**
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" + method.getName() + "方法");
        Object object = method.invoke(tager, args);
        if(object != null){
            System.out.println("获取到" + object.toString() + "的名字");
        }
        return object;
    }
}

接下写测试类

package com.honizon.proxy;

import com.honizon.Dynamic.personHandler;
import com.honizon.proxy.impl.studentProxy;
import com.honizon.proxy.impl.teacherProxy;

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

public class proxyTest {

    public static void main(String[] args) {
        //创建一个被代理的对象
        personProxy student = new studentProxy();
        //创建一个与代理对象相关联的InvocationHandler
        InvocationHandler stuHandler = new personHandler<personProxy>(student);
        //动态生成代理对象,并将学生传给代理对象
        personProxy teacher = (personProxy) Proxy.newProxyInstance(personProxy.class.getClassLoader(), new Class<?>[]{personProxy.class}, stuHandler);
        teacher.getName();
    }

}

看效果

Connected to the target VM, address: '127.0.0.1:64135', transport: 'socket'
Disconnected from the target VM, address: '127.0.0.1:64135', transport: 'socket'
代理执行getName方法
张三
获取到被代理类的名字

Process finished with exit code 0
  • 总结
    相对直接调用,代理模式的好处在于在执行方法之前做些其他处理,而动态代理的优势在于他的代理是有代码指令完成的,不需要手动去创建。而且每个方法在invoke里统一执行,方便管理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值