资讯动态

深入理解:动态代理的底层原理(即,深入理解:Spring框架中的面向切面编程(AOP))

发布时间:2026/8/23 13:44:01 来源:尧图企业网站定制
深入理解动态代理的底层原理即深入理解Spring框架中的面向切面编程AOP一·代理设计模式的原理:二·为什么需要动态代理三·动态代理的简单实现四·综上所述这就是动态代理的底层机制也是spring框架的AOP底层原理一·代理设计模式的原理:使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。二·为什么需要动态代理从作用上来说使用静态代理也可以完成在不改变源码的情况下,对已有的方法进行增强(运行期增强)功能的代理作用。但是静态代理特征是代理类和目标对象的类都是在编译期间确定下来不利于程序的扩展。同时每一个代理类只能为一个接口服务这样一来程序开发中必然产生过多的代理。最好可以通过一个代理类完成全部的代理功能。Spring框架中的AOP的底层实现原理就是动态代理。三·动态代理的简单实现1.先创建一个Person接口/** * 创建一个人类接口并定义两个未具体实现方法 */publicinterfacePerson{StringgetName();//获取人的名字Stringeat(Stringfood);//吃食物}2.再写一个Person的实现类TeacherpublicclassTeacherimplementsPerson{OverridepublicStringgetName(){System.out.println(这是Teacher类的getName()方法);return王老师;}OverridepublicStringeat(Stringfood){System.out.println(这是Teacher类的eat()方法);returnfood;}}3.创建InvocationHandler接口的一个实现类PersonInvocationHandler并实现接口的invoke()方法。这一步实际就是写代理类部分注意看代码中的注释部分publicclassPersonInvocationHandlerimplementsInvocationHandler{//创建一个被代理类对象这里为了更加通用使用Object类型privateObjectobj;//利用构造方法注入被代理类对象publicPersonInvocationHandler(Objectobj){this.objobj;}/** * invoke(): 当我们通过代理类的对象调用某个方法时就会自动的调用invoke();将被代理类要执行的某个方法的功能就声明在invoke()中 * * param proxy 就是代理对象newProxyInstance方法的返回对象 * param method 指代的是我们所要调用真实对象的某个方法的Method对象 * param args 指代的是调用真实对象某个方法时接受的参数 * return 返回结果 * throws Throwable 抛出一个异常 */OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{//增强功能1System.out.println(在执行原方法之前增加的功能1这是代理类的invoke方法);//原本功能Method.invoke():方法可以调用被代理类中的方法但是需要传入被代理类的对象以及调用某个方法的参数。//这样书写相当于对原本对象的每个方法都会进行拦截代理一般实际情况都得进行方法名路由判断而不是对所有方法代理增强Objectresmethod.invoke(obj,args);//增强功能2System.out.println(在执行原方法之后增加的功能2这是代理类的invoke方法);//返回调用原方法的结果returnres;}}4.在需要获取动态代理类的某个类中使用“Proxy.newProxyInstance()”方法获取一个被代理类的动态代理类。这里我使用一个工厂类ProxyFactory2中的一个静态getProxyInstance方法中来获取动态代理类。工厂模式publicclassProxyFactory2{//创建一个静态方法用来统一获取各个类的代理类publicstaticObjectgetProxyInstance(Objectobj){//调用方法的时候需要注入一个被代理类对象obj//创建一个InvocationHandler类的实现类对象作为增强功能类就是上面创建PersonInvocationHandler类PersonInvocationHandlerinvocationHandlernewPersonInvocationHandler(obj);//obj: 指代被代理的类的对象/** * newProxyInstance(ClassLoader loader,Class?[] interfaces,reflect.InvocationHandler h):返回一个类的代理类 * newProxyInstance()方法的三个参数 * loader: 一个ClassLoader对象定义了由哪个ClassLoader对象来对生成的代理对象进行加载。就是获取一个类加载器。 * 一般我们自己写的类无论与代理类或被代理类有没有关系通过getClassLoader()方法获取的类加载器都是AppClassLoader这个系统类加载器 * interfaces: 一个Interface对象的数组表示的是我将要给我需要代理的对象提供一组什么接口如果我提供了一组接口给它那么这个代理对象就宣称实现了该接口(多态)这样我就能调用这组接口中的方法了 * 至少必须包含一个与被代理类公共的接口这里就是包含Person接口 * h: 一个InvocationHandler对象表示的是当我这个动态代理对象在调用方法的时候会关联到哪一个InvocationHandler对象上 */returnProxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),invocationHandler);}}验证一般我们自己写的类无论与代理类或被代理类有没有关系通过getClassLoader()方法获取的类加载器都是AppClassLoader这个系统类加载器例如随便创建一个类Mss中间什么都不写。使用Mss类获取类加载器与使用代理类当前类被代理类获取类加载器。测试结果都是AppClassLoader这个类加载器。5.创建一个测试类来测试获取不同类的代理类publicclassTestProxyFactory2{publicstaticvoidmain(String[]args){//创建被代理的类TeacherteachernewTeacher();//获取teacher类的动态代理类/** * 获取的动态代理类之后必须 强制转换 为 与被代理类公共接口的类型 * 例如下面的 Person接口而不是teacher类型或者student类型 */PersonproxyInstance(Person)ProxyFactory2.getProxyInstance(teacher);System.out.println(我们学校最漂亮的老师是proxyInstance.getName());System.out.println(-------------------------);System.out.println(她晚饭就吃proxyInstance.eat(香蕉));System.out.println(-------------------------);}}测试结果四·综上所述这就是动态代理的底层机制也是spring框架的AOP底层原理

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价