前言:  早期学习了动态代理在实际开发中的使用场景和使用方法,我们也知道了最经典的mybatis的mapper就是采用动态代理来实现的,那么动态代理的背后是怎样的原理?为什么能实现动态代理?为什么动态代理只可以代理接口,而无法代理普通类?为什么动态代理需要传入类的classLoder和接口?带着这些疑问,我们来开启本期的主题:探究动态代理的内部原理。

本篇博客的目录

一:动态代理的基本使用方法

二:动态代理的内部运行过程

三:几个相关的问题

四:总结

一:动态代理的基本使用方法

 1.1:简单例子

首先我们来模拟一个简单的动态代理的过程:某歌手去参加一个晚会,需要唱歌,他在演奏的过程中需要别人来报幕:演奏开始、演奏结束,每个歌手都遵循这样的过程,在歌手进行表演的过程,穿插着主持人的开场白和结语,我们来用代码模拟这个场景:

1.2:代理接口

首先我们来定义一个singer接口表示我们将要代理的接口:

复制代码
public interface Singer {     /**      * 表演      * @param soonName      */    public void perform(String soonName); }
复制代码

1.3:接口的具体实现类

复制代码
public class Jay implements Singer {        public void perform(String soonName) {         System.out.println("接下来我为大家唱一首"+soonName);     } }
复制代码

1.4:辅助类,用来模拟注册人的前后台词

复制代码
public class Presenter  {      public void before(){         System.out.println("请开始你的表演!");     }      public void after(){         System.out.println("表演结束,大家鼓掌!");     } }
复制代码

1.5:具体的代理类

  这里用proxy.newProxyInstance来创建一个代理类,传入原始类的类加载器和接口与接口InvocationHandler,同时插入Presenter类的before与after方法,用于前置和后置处理

复制代码
public class SingerProxy {     private Presenter presenter;     public SingerProxy(Presenter presenter){        this.presenter = presenter;    }     /**      * 获取代理对象      * @return     */    public Singer getProxy(){          final Singer jay = new Jay();         Singer singerProxy = (Singer)Proxy.newProxyInstance(jay.getClass().getClassLoader(), jay.getClass().getInterfaces(), new InvocationHandler() {」             public Object invoke(Object proxy, Method me