Java AOP知识详细介绍

发布时间 - 2026-01-10 22:36:30    点击率:

Java AOP

AOP知识整理

AOP(Aspect-Oriented Programming):面向切面的编程。OOP(Object-Oriented Programming)面向对象的编程。对于OOP我们已经再熟悉不过了,对于AOP,可能我们会觉得是一种新特性,其实AOP是对OOP的一种补充,OOP面向的是纵向编程,继承、封装、多态是其三大特性,而AOP是面向横向的编程。

面向切面编程(AOP)通过提供另外一种思考程序结构的途经来弥补面向对象编程(OOP)的不足。在OOP中模块化的关键单元是类(classes),而在AOP中模块化的单元则是切面。切面能对关注点进行模块化,例如横切多个类型和对象的事务管理。
AOP框架是spring的一个重要组成部分。但是Spring IoC容器并不依赖于AOP,这意味着你有权利选择是否使用AOP,AOP做为Spring IoC容器的一个补充,使它成为一个强大的中间件解决方案。

AOP在Spring Framework中的作用

  • 提供声明式企业服务,特别是为了替代EJB声明式服务。最重要的服务是声明*务管理(这个我想是AOP使用最多的一处了)。
  • 允许用户实现自定义切面,用AOP来完善OOP的使用。

1.AOP概念:

学习AOP,当然得先了解一下其众多的概念性术语:

  • 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式)或者基于@Aspect注解的方式来实现。
  • 连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。
  • 通知(Advice):在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知(通知的类型将在后面部分进行讨论)。许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。
  • 切入点(Pointcut):匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
  • 引入(Introduction):用来给一个类型声明额外的方法或属性(也被称为连接类型声明(inter-type declaration))。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用引入来使一个bean实现IsModified接口,以便简化缓存机制。
  • 目标对象(Target Object): 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。
  • AOP代理(AOP Proxy):AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
  • 织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

通知类型:

  • 前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
  • 后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
  • 异常通知(After throwing advice):在方法抛出异常退出时执行的通知。
  • 最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • 环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。

环绕通知是最常用的通知类型。和AspectJ一样,Spring提供所有类型的通知,我们推荐你使用尽可能简单的通知类型来实现需要的功能。例如,如果你只是需要一个方法的返回值来更新缓存,最好使用后置通知而不是环绕通知,尽管环绕通知也能完成同样的事情。用最合适的通知类型可以使得编程模型变得简单,并且能够避免很多潜在的错误。比如,你不需要在JoinPoint上

调用用于环绕通知的proceed()方法,就不会有调用的问题。

在这里,基于@AspectJ的AOP我就不多写了,因为我更青睐于Spring中使用ProxyFactoryBean创建AOP代理。

2.使用ProxyFactoryBean创建AOP代理:

在Spring里创建一个AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean。 这个类对应用的切入点和通知提供了完整的控制能力(包括它们的应用顺序)。像其它的FactoryBean实现一样,ProxyFactoryBean引入了一个间接层。如果你定义一个名为foo的ProxyFactoryBean, 引用foo的对象看到的将不是ProxyFactoryBean实例本身,而是一个ProxyFactoryBean实现里getObject() 方法所创建的对象。 这个方法将创建一个AOP代理,它包装了一个目标对象。

ProxyFactoryBean类本身也是一个JavaBean,其属性主要有如下用途:

  • 指定你希望代理的目标对象
  • 指定是否使用CGLIB。

一些主要属性从org.springframework.aop.framework.ProxyConfig里继承下来(这个类是Spring里所有AOP代理工厂的父类)。这些主要属性包括:

  • proxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建。
  • optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略。 除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于CGLIB代理; 对于JDK动态代理(缺省代理)无效。
  • frozen:如果一个代理配置是frozen的,就不允许对该配置进行修改。 这在简单优化和不希望调用者在代理创建后操作代理(通过Advised接口) 时很有用。缺省值为false,即可以进行类似添加附加通知的操作。
  • exposeProxy:决定当前代理是否被暴露在一个ThreadLocal 中以便被目标对象访问。如果目标对象需要获取代理而且exposeProxy属性被设为 true,目标对象可以使用AopContext.currentProxy()方法。
  • aopProxyFactory:使用AopProxyFactory的实现。这提供了一种方法来自定义是否使用动态代理,CGLIB或其它代理策略。 缺省实现将根据情况选择动态代理或者CGLIB。一般情况下应该没有使用这个属性的需要;它是被设计来在Spring 1.1中添加新的代理类型的。

ProxyFactoryBean中需要说明的其它属性包括:

  • proxyInterfaces:需要代理的接口名的字符串数组。 如果没有提供,将为目标类使用一个CGLIB代理。
  • interceptorNames:Advisor的字符串数组,可以包括拦截器或其它通知的名字。 顺序是很重要的,排在前面的将被优先服务。就是说列表里的第一个拦截器将能够第一个拦截调用。

这里的名字是当前工厂中bean的名字,包括父工厂中bean的名字。这里你不能使用bean的引用因为这会导致ProxyFactoryBean忽略通知的单例设置。
你可以把一个拦截器的名字加上一个星号作为后缀(*)。这将导致这个应用程序里所有名字以星号之前部分开头的通知器都被应用。

单例:工厂是否应该返回同一个对象,不论方法getObject()被调用的多频繁。 多个FactoryBean实现都提供了这个方法。缺省值是true。 如果你希望使用有状态的通知--例如,有状态的mixin--可以把单例属性的值设置为false来使用原型通知。

3.基于JDK和CGLIB的代理:

如果一个需要被代理的目标对象的类(后面将简单地称它为目标类)没有实现任何接口,那么一个基于CGLIB的代理将被创建。 这是最简单的场景,因为JDK代理是基于接口的,没有接口意味着没有使用JDK进行代理的可能.

如果ProxyFactoryBean的proxyTargetClass属性被设为true,那么一个基于CGLIB的代理将创建。 这样的规定是有意义的,遵循了最小惊讶法则(保证了设定的一致性)。甚至当ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名, 而proxyTargetClass属性被设置为true仍然将实际使用基于CGLIB的代理。

如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名,一个基于JDK的代理将被创建。 被创建的代理将实现所有在proxyInterfaces属性里被说明的接口; 如果目标类实现了全部在proxyInterfaces属性里说明的接口以及一些额外接口,返回的代理将只实现说明的接口而不会实现那些额外接口。

如果ProxyFactoryBean的proxyInterfaces属性没有被设置, 但是目标类实现了一个(或者更多)接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口, 一个基于JDK的代理将被创建。被实际代理的接口将是目标类所实现的全部接口; 实际上,这和在proxyInterfaces属性中列出目标类实现的每个接口的情况是一样的。 然而,这将显著地减少工作量以及输入错误的可能性。

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


# Java  # AOP  # AOP详解  # AOP整理知识  # Java Spring AOP之PointCut案例详解  # Java aop面向切面编程(aspectJweaver)案例详解  # Java JDK动态代理(AOP)用法及实现原理详解  # Java动态代理和AOP应用示例  # Java JDK动态代理(AOP)的实现原理与使用详析  # java Spring AOP详解及简单实例  # 图解JAVA中Spring Aop作用  # Java之Spring AOP 实现用户权限验证  # Java SpringBoot整合SpringCloud  # 一篇文章教你将JAVA的RabbitMQz与SpringBoot整合  # Java SpringBoot启动指定profile的8种方式详解  # Java SpringBoot在RequestBody中高效的使用枚举参数原理案例详解  # Java SpringBoot实现AOP  # 多个  # 将被  # 如果你  # 设置为  # 抛出  # 设为  # 自定义  # 拦截器  # 这是  # 创建一个  # 你可以  # 第一个  # 实现了  # 可以使用  # 横切  # 或其它  # 来实现  # 这将  # 使用这个  # 点上 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何确保FTP站点访问权限与数据传输安全?  Internet Explorer官网直接进入 IE浏览器在线体验版网址  如何在景安服务器上快速搭建个人网站?  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  Laravel如何生成URL和重定向?(路由助手函数)  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】  HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】  深圳网站制作的公司有哪些,dido官方网站?  html5怎么画眼睛_HT5用Canvas或SVG画眼球瞳孔加JS控制动态【绘制】  制作旅游网站html,怎样注册旅游网站?  laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法  中山网站推广排名,中山信息港登录入口?  如何在 React 中条件性地遍历数组并渲染元素  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  JavaScript如何实现错误处理_try...catch如何捕获异常?  JavaScript Ajax实现异步通信  详解MySQL数据库的安装与密码配置  如何实现建站之星域名转发设置?  Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑  高端网站建设与定制开发一站式解决方案 中企动力  高端云建站费用究竟需要多少预算?  Laravel如何优化应用性能?(缓存和优化命令)  在线教育网站制作平台,山西立德教育官网?  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  JS去除重复并统计数量的实现方法  Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康  奇安信“盘古石”团队突破 iOS 26.1 提权  EditPlus 正则表达式 实战(3)  如何选择PHP开源工具快速搭建网站?  Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势  网站制作报价单模板图片,小松挖机官方网站报价?  Laravel中的Facade(门面)到底是什么原理  Laravel如何实现文件上传和存储?(本地与S3配置)  如何在万网利用已有域名快速建站?  微信小程序 闭包写法详细介绍  如何用免费手机建站系统零基础打造专业网站?  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  如何用低价快速搭建高质量网站?  Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】  如何在阿里云ECS服务器部署织梦CMS网站?  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  javascript中对象的定义、使用以及对象和原型链操作小结  如何在香港免费服务器上快速搭建网站?  HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  如何利用DOS批处理实现定时关机操作详解  laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法  Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复