我们之前学习到,类加载器是通过类的.classLoader()方法,将.class文件从我们的磁盘中加载到jvm虚拟机中,形成字节码文件。
反射是通过类加载形成的字节码文件,把类里的信息映射成相应的类,并进行各自的操作。
今天,我们学到的动态代理技术使我们整个java学习中最关键也是最重要的一问技术,是我们之后学习Java框架的基础,不会动态代理,那么学习框架的时候是学不明白的。
接下来,让我们一起来弄明白这个动态代理。
代理模式
其实大家都知道一些什么汽车代理,微商代理或者是手机代理商,换句话说他们就是替商品的厂家买东西,厂家委托代理销售期产品。
在这里,我们不需要知道代理背后的厂家是谁,也就是委托者对我们不可见;而这些代理可能使用朋友圈为主题目标,这样也相当于代理帮助厂家额外做了一次客户的过滤。
在Java中我们把前者抽象为代理类,后者抽象为委托类(被代理类)。
静态代理
举个简单例子,大家都有交作业的经验吧,那我我们的班长就是代理,班主任就是委托者。
我们首先建一个Person接口。这个接口就是学生(被代理类),和班长(代理类)的公共接口,他们都要去给老师交作业,而我们学生交作业的时候就可以让班长来帮我们去做。
Student类实现Person接口,在这里我们让学生具体实现上交作业这个动作。
StudentsProxy类,学生代理也就是班长的类,我们在这个类中实现了Person的接口,同时,代理类中还有一个学生对象,这样学生就可以像班长提交作业,由班长替我们交作业。
下面测试一下,运行结果就是,“女陶上交班主任作业”。
在这里如果班长想表扬我女陶,可以在班长的类直接加入,不需要在我源代码里面输入。如下图。
这样的操作,就是使用代理模式一个很大的优点。直白一点说,就是在Spring中的面向切面编程(AOP)。
动态代理
代理类在程序运行时创建的代理方式被成为动态代理。 在上面的例子中,我们可以看到,班长这个代理类是我们自己定义好的,在程序运行之前就提前编译好让我们使用的。
动态代理,顾名思义就是代理类在程序运行时根据我们给的指示动态生成的。
同样的举个例子:
我们想要在刚刚的交作业上面加一个签到的方法,如果是一个交作业的方法前加,那我们直接加入就好,那么如果还有很多的方法呢,是不是很麻烦,我们看看动态代理怎么实现的。
这次我们改成上交班费。
动态代理简单实现
同样的定义一个Person
我们创建一个被代理的student类。
我们使用时间检测工具,计算出该方法的运行时间
我们通过创建StuInvocationHandler类,并且实现InvocationHandler接口,这个类中有一个被代理对象的实例叫做target。
而InvocationHandler中有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法。
我们在nvoke方法中执行被代理对象target的相应方法。在代理过程中,我们可以在真正执行被代理对象的方法前加入自己的东西去处理。
这也是Spring中的AOP实现的主要原理,这里我们在这里有关联到一个同样重要的Java中反射方面的基础知识。一起来学大数据|Java中的反射机制
我们把上面的工作完成之后,就可以具体来创建动态代理对象了,上面的例子简单的介绍了我们该如何创建动态代理对象。
接下来我们看看简化的方式创建动态代理对象:
我们在执行ProxyTest类的时候,我们想来回想一下,我们开始创建了一个需要被代理的同学张三,之后我们将张三对象传给stuHandler,在我们创建这个代理stuProxy的时候,我们又将stuHandler作为了参数,最后执行StuInvocationHandler中的invoke方法。因此我们看到了下面这样的运行结果。
总结:
我们在刚刚开始就提到,动态代理的明显优势在它可以很便捷的统一的处理代理类的方法,并不需要修改每个代理类中的方法。
其中的原因就是我们所有被代理执行的方法,都是通过在InvocationHandler中的invoke方法调用的,所以只要在invoke的方法中我们做统一的处理,就可实现对所有的被代理的方法进行相同的操作了。
例如,我们在这里写的对方法的计时,我们只做了很少的代码量就可以让所有方法都去计算运算时间。
上面就是我们对今天学习的动态代理,其中我们还了解了什么事代理,静态代理的一些例子。Spring的AOP的实现其实也是用了Proxy和InvocationHandler。
明天,我们继续学习Java中的一些常用类。
今天的学习有帮助到大家的话,关注支持一下呗~
感谢坚持关注的朋友~
世界很大,幸好有你~
欢迎在评论区留下你的问题或困惑,我将每天与你分享我的观点和心得。
聚焦最新科技咨讯,探寻未来智能领域,我是Mario女陶。