当前位置: 首页 > news >正文

SpringAOP原理:手写动态代理实现

0、基础知识

        AOP我们知道,是在不修改源代码的情况下,为代码添加一些新功能的技术。通过动态代理,可以在不修改原始类代码的前提下,对方法进行拦截和增强。
        动态代理常用于在不改变原有业务逻辑的情况下,对方法的调用进行额外的处理,比如日志记录、性能监控、事务管理等。它实现了面向切面编程(AOP)的核心概念。

1、动态代理  

        AOP其实就是先通过“一些办法”拿到“代理对象”,再对这个代理对象添加新方法。

动态代理的两种办法:

1.1 JDK代理:基于接口的动态代理技术。

        方法:通过目标接口,创建接口实现类,动态地在运行时内存里生成代理对象,其拥有目标对象的原方法实现,最后通过代理对象来增加新功能。

        看文字有些抽象,现在手动用代码实现一个JDK代理的AOP技术,根据jdk1.8手册找到Proxy类,通过newInstance方法实现动态代理对象的创建。

 “Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。”

(1)准备接口和实现类

//=========================接口============================
public interface UserDao {public int add(int a,int b);public String update(String id);
}//=========================实现类============================
public class UserDaoImpl implements UserDao{@Overridepublic int add(int a, int b) {System.out.println("add.......");return a+b;}@Overridepublic String update(String id) {System.out.println("update===========");return id;}
}

(2)创建UserDao的代理对象,调用增强方法
需要注意:InvocationHandler接口里有invoke方法必须实现,而调用代理对象的任何方法,实质都是在执行invoke方法。           

public class JDKProxy {public static void main(String[] args) {
/**
newProxyInstance的三个内容:类加载器、要实现的接口的class、
和InvocationHandler(这是个接口,里面写的增强类的具体逻辑)
*/Class[] interfaces = {UserDao.class};UserDaoImpl userDao = new UserDaoImpl();UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserDaoProxy(userDao));//生成的“dao”就是代理对象实例。//也可以直接用匿名内部类的方法来写(new InvocationHandler)int add = dao.add(1, 2);//使用代理对象dao调用add的时候,无需改变add源码,却增强了功能。System.out.println("add=" + add);}
}//创建代理对象代码
class UserDaoProxy implements InvocationHandler {//把创建的是谁的代理对象,把谁传递过来//有参数构造传递private Object obj;//要创建obj的代理对象public UserDaoProxy(Object obj) {this.obj = obj;}//增强的逻辑:InvocationHandler接口里有invoke方法必须实现
//调用代理对象的任何方法,实质都是在执行invoke方法。@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//方法之前(增强)System.out.println("方法之前执行...."+method.getName()+" :传递的参数..." + Arrays.toString(args));//被增强的方法执行(原模块功能不变)Object res = method.invoke(obj, args);//res=3//方法之后(增强)System.out.println("方法之后执行...."+obj);return res;}
}

        但是有个遗留问题,invoke函数究竟是如何被调用的,往下看了源码也没有分析出来,个人推测是这样的:

        因为传入的obj其实就是要动态代理的原对象,但我们不知道具体执行什么方法,此时dao还未调用add方法。但调用了以后,invoke方法却能够自动调用、增强方法,内部应该是采用反射的方法,拿到“add”这个方法名称,通过getMethod反射出方法的类对象,再用method.invoke(具体对象)来实现方法的调用,从而调用add,并完成前后的增强。

1.2 cglib:基于父类的动态代理技术。

        方法:为目标对象动态地生成子对象,其具有了父类的方法(实际不是继承)
        实现类似,此处不做代码示例。

http://www.lryc.cn/news/132350.html

相关文章:

  • 【旅游度假】Axure酒店在线预订APP原型图 旅游度假子模块原型模板
  • Android JNI系列详解之CMake和ndk-build编译工具介绍
  • 【Linux取经路】解析环境变量,提升系统控制力
  • TCP编程流程(补充)
  • 每天一道leetcode:433. 最小基因变化(图论中等广度优先遍历)
  • 【C++】做一个飞机空战小游戏(十)——子弹击落炮弹、炮弹与飞机相撞
  • 去除UI切图边缘上多余的线条
  • Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor解析
  • 【LeetCode动态规划】详解买卖票I~IV,经典dp题型买
  • 【深入探究人工智能】:常见机器学习算法总结
  • 设计模式之解释器模式详解及实例
  • Nodejs沙箱逃逸--总结
  • No115.精选前端面试题,享受每天的挑战和学习
  • Elasticsearch:语义搜索 - Semantic Search in python
  • Flink学习笔记(一)
  • [Raspberry Pi]如何用VNC遠端控制樹莓派(Ubuntu desktop 23.04)?
  • 17.HPA和rancher
  • VS2022远程Linux使用cmake开发c++工程配置方法
  • 《强化学习:原理与Python实战》——可曾听闻RLHF
  • STM32——RTC实时时钟
  • webSocket 开发
  • c#设计模式-结构型模式 之 代理模式
  • openpnp - 自动换刀的设置
  • 《HeadFirst设计模式(第二版)》第十章代码——状态模式
  • day-25 代码随想录算法训练营(19)回溯part02
  • PG逻辑备份与恢复
  • 图数据库_Neo4j和SpringBoot整合使用_实战创建明星关系图谱---Neo4j图数据库工作笔记0010
  • Linux网络编程:Socket套接字编程(Server服务器 Client客户端)
  • Mac OS下应用Python+Selenium实现web自动化测试
  • 每天一道leetcode:934. 最短的桥(图论中等广度优先遍历)