【从0开始学习Java | 第23篇】动态代理

📅 发布时间:2026/7/10 3:01:20 👁️ 浏览次数:
【从0开始学习Java | 第23篇】动态代理
重阳来啦第23篇我们聊动态代理——这是Java面试中中高级岗必问、Spring AOP底层核心、MyBatis插件、RPC框架都离不开的知识点。学会动态代理 直接秒杀 80% 的候选人一、先搞清楚到底什么是代理生活例子你想找周杰伦签名 → 你不会直接找周杰伦 → 你找他的经纪人代理→ 经纪人帮你转达、加点要求唱歌前先喝热水、最后还是周杰伦签的名。Java里的代理就是这个道理。二、静态代理 vs 动态代理超级清晰对比项目静态代理动态代理今天主角代理类写法自己手动写一个代理类运行期间由JVM自动生成代理类代码量一个接口要写一个代理类接口多了爆炸无论多少接口一个动态代理搞定灵活性改个需求要改代理类代码完全动态随时换增强逻辑典型场景早期手写日志、事务Spring AOP、MyBatis Plugin、Dubbo等结论静态代理只是教学用的真实项目99.9%用动态代理三、Java动态代理有两种方式2026年仍然是这俩JDK动态代理必须实现接口← 今天重点面试问90%CGLIB动态代理可以代理没有接口的类← Spring默认用这个当目标类没接口我们先把JDK动态代理吃透四、JDK动态代理完整实现手敲3遍就能背出来场景明星只有唱歌的功能我们要在唱歌前后自动加“收钱”和“宣传”// 1. 定义通用能力接口publicinterfaceStar{voidsing(StringsongName);// 唱歌Stringdance();// 跳舞有返回值}// 2. 真实明星周杰伦publicclassJayChouimplementsStar{Overridepublicvoidsing(StringsongName){System.out.println(周杰伦唱songName收1000万);}OverridepublicStringdance(){System.out.println(周杰伦跳舞很帅~);return舞王;}}// 3. 动态代理的核心InvocationHandler真正干活的地方importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;publicclassStarHandlerimplementsInvocationHandler{privatefinalStartarget;// 被代理的真实对象publicStarHandler(Startarget){this.targettarget;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{// 前置增强System.out.println(【经纪人】接活谈价格签合同...);// 调用真实对象的方法这句是灵魂Objectresultmethod.invoke(target,args);// 后置增强System.out.println(【经纪人】宣传、发微博、收尾款...);returnresult;// 一定要返回不然有返回值的方法会返回null}}// 4. 测试类真正使用动态代理的地方importjava.lang.reflect.Proxy;publicclassTestDynamicProxy{publicstaticvoidmain(String[]args){// 真实对象StarjaynewJayChou();// 创建InvocationHandlerStarHandlerhandlernewStarHandler(jay);// 关键三行运行时动态生成代理对象StarproxyStar(Star)Proxy.newProxyInstance(jay.getClass().getClassLoader(),// 类加载器jay.getClass().getInterfaces(),// 被代理类实现的所有接口handler// InvocationHandler);// 使用代理对象完全感觉不到背后有经纪人proxyStar.sing(稻香);StringdanceResultproxyStar.dance();System.out.println(跳舞评价danceResult);// 看看代理对象到底是谁System.out.println(代理对象真实类型proxyStar.getClass().getName());// 输出$Proxy0 JVM动态生成的类}}运行结果【经纪人】接活谈价格签合同... 周杰伦唱稻香收1000万 【经纪人】宣传、发微博、收尾款... 【经纪人】接活谈价格签合同... 周杰伦跳舞很帅~ 【经纪人】宣传、发微博、收尾款... 跳舞评价舞王 代理对象真实类型com.sun.proxy.$Proxy0五、最重要的三行代码背下来面试必问StarproxyStar(Star)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),newStarHandler(target));这三行就是JDK动态代理的全部精华六、面试官最爱问的10个问题全部背熟动态代理和静态代理区别JDK动态代理为什么必须实现接口Proxy.newProxyInstance 三个参数分别是什么InvocationHandler 的 invoke 方法三个参数是什么如果被代理类没有接口能用JDK动态代理吗→ 不能用CGLIBSpring中默认用哪个→ 有接口用JDK没有接口用CGLIBSpring Boot2.x后默认CGLIB动态代理生成的 $Proxy0 是什么能反编译看看吗方法有返回值时invoke里要不要return→ 必须return method.invoke(…)动态代理的底层实现原理→ 就是上面这套反射 动态生成字节码能手写一个动态代理吗→ 现在你能闭着眼敲出来了七、终极小练习建议你现在就敲一遍需求用动态代理实现一个通用日志记录器对任意对象的所有方法调用都自动打印--- 开始执行sing(稻香) --- sing执行结束耗时15ms提示可以在invoke里记录System.currentTimeMillis()结语重阳恭喜你当你能完全手敲出上面的动态代理代码时恭喜你已经超越了市面上 80% 的 Java 程序员这就是为什么Spring能用几行注解就实现事务、缓存、权限控制的底层原理下一节我们直接上CGLIB动态代理 手撕Spring AOP底层原理准备好了吗现在你可以把上面代码完整敲一遍必须告诉我你跑通了吗有没有遇到什么问题想直接看CGLIB还是先来几个动态代理的变态面试题我在等你 来吧冲