🍊
翻译橙
🍊返回主站🤖参与贡献
  • hello,这里是翻译橙
  • spring boot参考文档
    • 1. 法律
    • 2. 寻求帮助
    • 3. 文档概述
    • 4. 入门
    • 5. 升级Spring Boot
    • 6. 使用 Spring Boot 进行开发
      • 6.1. 构建系统
      • 6.2. 构建你的代码
      • 6.3. 配置类
      • 6.4. 自动配置
      • 6.5. Spring Bean 和依赖注入
      • 6.6. 使用@SpringBootApplication注解
      • 6.7. 运行您的应用程序
      • 6.8. 开发者工具
      • 6.9. 打包您的生产应用程序
      • 6.10. 接下来读什么
    • 7.核心特性
      • 7.1. SpringApplication
      • 7.2. 外部化配置
      • 7.3.Profile配置
      • 7.4.日志记录
      • 7.5.国际化
      • 7.6 面向切面的编程
      • 7.7. JSON
      • 7.8. 任务执行与调度
      • 7.9. 单元测试
        • 7.9.1. 测试范围依赖
        • 7.9.2. 测试 Spring 应用程序
        • 7.9.3. 测试 Spring Boot 应用程序
        • 7.9.4. 测试容器
        • 7.9.5. 测试工具
      • 7.10. Docker Compose 支持
      • 7.11. 测试容器支持
      • 7.12. 创建您自己的自动配置
      • 7.13. Kotlin 支持
      • 7.14 SSL
      • 7.15.接下来要读什么
    • 8. 网络
      • 8.1. Servlet Web 应用程序
        • 8.1.1. “Spring Web MVC 框架”
        • 8.1.2. JAX-RS 和Jersey
        • 8.1.3. 嵌入式 Servlet 容器支持
      • 8.2 反应式网络应用程序
        • 8.2.1. “Spring WebFlux 框架”
        • 8.2.2. 嵌入式反应式服务器支持
        • 8.2.3. 反应式服务器资源配置
      • 8.3. 优雅关机
      • 8.4. spring安全
        • 8.4.1. MVC安全
        • 8.4.2. WebFlux 安全
        • 8.4.3. OAuth2
        • 8.4.4. SAML 2.0
      • 8.5. spring 会话
      • 8.6.GraphQL
      • 8.7. Spring HATEOAS
      • 8.8.接下来读什么
    • 9. 数据
      • 9.1. SQL数据库
      • 9.2. 使用 NoSQL 技术
      • 9.3. 接下来读什么
    • 10. 消息
      • 10.1. JMS
      • 10.2. AMQP
      • 10.3. Apache Kafka 支持
      • 10.4. Apache Pulsar 支持
      • 10.5. RSocket
      • 10.6. Spring Integration
      • 10.7. WebSockets
      • 10.8. What to Read Next
    • 11. IO
      • 11.1. 缓存
      • 11.2. Hazelcast
      • 11.3. Quartz 调度程序
      • 11.4. 发送电子邮件
      • 11.5. 验证
      • 11.6. 调用 REST 服务
      • 11.7. web services
      • 11.8. 使用 JTA 进行分布式事务
      • 11.9. 接下来读什么
    • 12. 容器镜像
  • Spring核心功能
    • 1.IOC容器和Bean简介
      • 1.2. 容器概述
      • 1.3. Bean概述
      • 1.4. 依赖项
        • 1.4.1. 依赖注入
        • 1.4.2. 详细的依赖关系和配置
        • 1.4.3. 使用depends-on
        • 1.4.4. 延迟初始化的 Bean
        • 1.4.5. 自动装配协作者
        • 1.4.6. 方法注入
    • 2. Resources
      • 2.1. 介绍
      • 2.2. Resource接口
      • 2.3. 内置Resource实现
      • 2.4. ResourceLoader接口
      • 2.5. ResourcePatternResolver接口
      • 2.6. ResourceLoaderAware接口
      • 2.7. 资源作为依赖
      • 2.8. 应用程序上下文和资源路径
    • 3. 验证、数据绑定和类型转换
      • 3.1. 使用 Spring 的 Validator 接口进行验证
      • 3.2. 将代码解析为错误消息
      • 3.3. Bean 操作和BeanWrapper
      • 3.4. spring类型转换
      • 3.5. spring字段格式
      • 3.6. 配置全局日期和时间格式
      • 3.7. Java Bean 验证
    • 4. SpEL表达式
    • 5. Spring 面向切面编程
      • 5.1. AOP 概念
      • 5.2. Spring AOP 的能力和目标
      • 5.3. AOP 代理
      • 5.4. @AspectJ 支持
        • 5.4.1. 启用@AspectJ 支持
        • 5.4.2. 声明一个切面
        • 5.4.3. 声明切入点
        • 5.4.4. 声明切点
        • 5.4.5. 切面说明
        • 5.4.6. 切面实例化模型
        • 5.4.7. AOP 示例
      • 5.5. 基于模式的 AOP 支持
      • 5.6. 选择要使用的 AOP 声明样式
      • 5.7. 混合切面类型
      • 5.8. 代理机制
      • 5.9. @AspectJ 代理的程序化创建
      • 5.10. 在 Spring 应用程序中使用 AspectJ
      • 5.11.更多资源
    • 6. Spring AOP API
      • 6.1. Spring中的切入点API
      • 6.2. Spring 中的 Advice API
      • 6.3. Spring 中的 Advisor API
      • 6.4. 使用ProxyFactoryBean创建 AOP 代理
      • 6.5. 简洁的代理定义
      • 6.6. 以编程方式创建 AOP 代理ProxyFactory
      • 6.7. 操作切面对象
      • 6.8. 使用“自动代理”工具
      • 6.9. 使用TargetSource实现
      • 6.10. 定义新的切面类型
    • 7. 空指针安全
    • 8. 数据缓冲器和编解码器
    • 9. 日志
    • 10. 附录
      • 10.1. XML 模式
      • 10.2. 自定义XML Schema
        • 10.2.1. 创作 Schema
        • 10.2.2. 编码一个NamespaceHandler
        • 10.2.3. 使用BeanDefinitionParser
        • 10.2.4. 注册处理程序和模式
        • 10.2.5. 在 Spring XML 配置中使用自定义扩展
        • 10.2.6. 更详细的例子
      • 10.3. 应用程序启动步骤
  • 使用redis实现分布式锁
  • Java 安全标准算法名称
  • JDK 9 JEP
  • JDK 10 JEP
  • 人件
    • 《人件》
    • 第一部分 管理人力资源
      • 01 此时此刻,一个项目正在走向失败
      • 02 干酪汉堡,做一个,卖一个
      • 03 维也纳在等你
      • 04 质量——如果时间允许
      • 05 再谈帕金森定律
      • 06 苦杏素
    • 第二部分 办公环境
      • 07 家具警察
      • 08 “朝九晚五在这里啥也完成不了。”
      • 09 在空间上省钱
      • 间奏曲:生产效率度量和不明飞行物
      • 10 大脑时问与身体时间
      • 11 电话
      • 12 门的回归
      • 13 采取保护步骤
    • 第三部分 正确的人
      • 14 霍恩布洛尔因素
      • 15 谈谈领导力
      • 16 雇一名杂耍演员
      • 17 与他人良好合作
      • 18 童年的终结
      • 19 在这儿很开心
      • 20 人力资本
    • 第四部分 高效团队养成
      • 21 整体大于部分之和
      • 22 黑衣团队
      • 23 团队自毁
      • 24 再谈团队自毁
      • 25 竞争
      • 26 一顿意面晚餐
      • 27 敞开和服
      • 28 团队形成的化学反应
    • 第五部分 沃土
      • 29 自我愈复系统
      • 30 与风险共舞
      • 3l 会议、独白和交流
      • 32 终极管理罪恶得主是……
      • 33 “邪恶”电邮
      • 34 让改变成为可能
      • 35 组织型学习
      • 36 构建社区
    • 第六部分 快乐地工作
      • 37 混乱与秩序
      • 38 自由电子
      • 39 霍尔加·丹斯克
由 GitBook 提供支持
在本页

这有帮助吗?

在GitHub上编辑
  1. Spring核心功能
  2. 5. Spring 面向切面编程
  3. 5.4. @AspectJ 支持

5.4.3. 声明切入点

上一页5.4.2. 声明一个切面下一页5.4.4. 声明切点

最后更新于1年前

这有帮助吗?

切入点确定连接点,从而使我们能够控制通知何时运行。Spring AOP 仅支持 Spring bean 的方法执行连接点,因此您可以将切入点视为匹配 Spring bean 上的方法执行。切入点声明有两部分:一个包含名称和任何参数的签名和一个切入点表达式,它准确地确定我们感兴趣的方法执行。在 AOP 的 @AspectJ 注解样式中,切入点签名由常规方法定义提供, 切入点表达式使用@Pointcut注解表示(作为切入点签名的方法必须有void返回类型)。

一个示例可能有助于明确切入点签名和切入点表达式之间的区别。以下示例定义了一个名为的切入点anyOldTransfer,它与任何名为transfer 的方法的执行相匹配:

@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature

形成@Pointcut注解值的切入点表达式是常规的 AspectJ 切入点表达式。有关 AspectJ 切入点语言的完整讨论,请参阅(以及扩展的 )或有关 AspectJ 的书籍之一(例如Colyer 等人的Eclipse AspectJ或**AspectJ in Action,拉姆尼瓦斯·拉达德)。

支持的切入点指示符

Spring AOP 支持在切入点表达式中使用以下 AspectJ 切入点指示符 (PCD):

  • execution:用于匹配方法执行连接点。这是使用 Spring AOP 时使用的主要切入点指示符。

  • within: 限制匹配到特定类型内的连接点(使用 Spring AOP 时执行匹配类型内声明的方法)。

  • this:限制匹配到连接点(使用 Spring AOP 时方法的执行),其中 bean 引用(Spring AOP 代理)是给定类型的实例。

  • target:将匹配限制在目标对象(被代理的应用程序对象)是给定类型的实例的连接点(使用 Spring AOP 时方法的执行)。

  • args: 限制匹配到参数是给定类型的实例的连接点(使用 Spring AOP 时方法的执行)。

  • @target:限制匹配到连接点(使用 Spring AOP 时方法的执行),其中执行对象的类具有给定类型的注解。

  • @args:将匹配限制为连接点(使用 Spring AOP 时方法的执行),其中传递的实际参数的运行时类型具有给定类型的注解。

  • @within:将匹配限制为具有给定注解的类型内的连接点(使用 Spring AOP 时执行在具有给定注解的类型中声明的方法)。

  • @annotation:限制匹配到连接点的主题(在 Spring AOP 中运行的方法)具有给定注解的连接点。

其他切入点类型

完整的 AspectJ 切入点语言支持 Spring 中不支持的其他切入点指示符:call、get、set、preinitialization、 staticinitialization、initialization、handler、adviceexecution、withincode、cflow、 cflowbelow、if、@this和@withincode。在 Spring AOP 解释的切入点表达式中使用这些切入点指示符会导致抛出IllegalArgumentException异常。

Spring AOP 支持的切入点指示符集可能会在未来的版本中扩展,以支持更多的 AspectJ 切入点指示符。

由于 Spring AOP 将匹配限制为仅方法执行连接点,因此前面对切入点指示符的讨论给出了比您在 AspectJ 编程指南中找到的更窄的定义。此外,AspectJ 本身具有基于类型的语义,并且在执行连接点处,this和target两者都引用同一个对象:执行方法的对象。Spring AOP 是一个基于代理的系统,它区分代理对象本身(绑定到this)和代理背后的目标对象(绑定到target)。

Spring AOP 还支持一个名为bean的PCD. 此 PCD 允许您将连接点的匹配限制为特定命名的 Spring bean 或一组命名的 Spring bean(使用通配符时)。bean PCD具有以下形式:

bean(idOrNameOfBean)

idOrNameOfBean令牌可以是任何 Spring bean 的名称。提供了使用*字符的有限通配符支持,因此,如果您为 Spring bean 建立了一些命名约定,则可以编写一个beanPCD 表达式来选择它们。与其他切入点指示符的情况一样,beanPCD 也可以与&&(and)、||(or) 和!(negation) 运算符一起使用。

beanPCD 仅在 Spring AOP 中受支持,在本机 AspectJ 编织中不支持。它是 AspectJ 定义的标准 PCD 的特定于 Spring 的扩展,因此不适用于@Aspect模型中声明的切面。PCD在bean实例级别(基于 Spring bean 名称概念)而不是仅在类型级别(基于编织的 AOP 受限)运行。基于实例的切入点指示符是 Spring 基于代理的 AOP 框架的一种特殊功能,它与 Spring bean 工厂的紧密集成,通过名称来识别特定的 bean 是自然而直接的。

组合切入点表达式

您可以使用&&,|| 和!组合切入点表达式。您还可以按名称引用切入点表达式。以下示例显示了三个切入点表达式:

@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {} 

@Pointcut("within(com.xyz.myapp.trading..*)")
private void inTrading() {} 

@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {} 

如前所述,使用较小的命名组件构建更复杂的切入点表达式是最佳实践。当按名称引用切入点时,应用正常的 Java 可见性规则(您可以看到相同类型的私有切入点、层次结构中的受保护切入点、任何地方的公共切入点,等等)。可见性不影响切入点匹配。

共享通用切入点定义

在使用企业应用程序时,开发人员通常希望从多个切面引用应用程序的模块和特定的操作集。我们通知为此目的定义一个捕获通用切入点表达式的CommonPointcuts切面。这样的切面通常类似于以下示例:

package com.xyz.myapp;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class CommonPointcuts {

    /**
     * A join point is in the web layer if the method is defined
     * in a type in the com.xyz.myapp.web package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.myapp.web..*)")
    public void inWebLayer() {}

    /**
     * A join point is in the service layer if the method is defined
     * in a type in the com.xyz.myapp.service package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.myapp.service..*)")
    public void inServiceLayer() {}

    /**
     * A join point is in the data access layer if the method is defined
     * in a type in the com.xyz.myapp.dao package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.myapp.dao..*)")
    public void inDataAccessLayer() {}

    /**
     * A business service is the execution of any method defined on a service
     * interface. This definition assumes that interfaces are placed in the
     * "service" package, and that implementation types are in sub-packages.
     *
     * If you group service interfaces by functional area (for example,
     * in packages com.xyz.myapp.abc.service and com.xyz.myapp.def.service) then
     * the pointcut expression "execution(* com.xyz.myapp..service.*.*(..))"
     * could be used instead.
     *
     * Alternatively, you can write the expression using the 'bean'
     * PCD, like so "bean(*Service)". (This assumes that you have
     * named your Spring service beans in a consistent fashion.)
     */
    @Pointcut("execution(* com.xyz.myapp..service.*.*(..))")
    public void businessService() {}

    /**
     * A data access operation is the execution of any method defined on a
     * dao interface. This definition assumes that interfaces are placed in the
     * "dao" package, and that implementation types are in sub-packages.
     */
    @Pointcut("execution(* com.xyz.myapp.dao.*.*(..))")
    public void dataAccessOperation() {}

}

您可以在需要切入点表达式的任何地方引用在此类切面中定义的切入点。例如,要使服务层具有事务性,您可以编写以下代码:

<aop:config>
    <aop:advisor
        pointcut="com.xyz.myapp.CommonPointcuts.businessService()"
        advice-ref="tx-advice"/>
</aop:config>

<tx:advice id="tx-advice">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

例子

Spring AOP 用户可能execution最常使用切入点指示符。执行表达式的格式如下:

execution(modifiers-pattern?
			ret-type-pattern
			declaring-type-pattern?name-pattern(param-pattern)
			throws-pattern?)

以下示例显示了一些常见的切入点表达式:

  • 任何公共方法的执行:

    execution(public * *(..))
  • 名称以 开头的任何方法的执行set:

    execution(public * *(..))
  • AccountService接口定义的任何方法的执行:

    execution(* com.xyz.service.AccountService.*(..))
  • 包中定义的任何方法的执行service:

    execution(* com.xyz.service.*.*(..))
  • 服务包或其子包之一中定义的任何方法的执行:

    execution(* com.xyz.service..*.*(..))
  • 服务包中的任何连接点(仅在 Spring AOP 中执行方法):

    within(com.xyz.service.*)
  • 服务包或其子包之一中的任何连接点(仅在 Spring AOP 中执行方法):

    within(com.xyz.service..*)
  • AccountService代理实现接口的任何连接点(仅在 Spring AOP 中执行方法) :

    this(com.xyz.service.AccountService)
  • AccountService目标对象实现接口的任何连接点(仅在 Spring AOP 中执行方法) :

    target(com.xyz.service.AccountService)
  • 任何接受单个参数且在运行时传递的参数为Serializable的连接点(仅在 Spring AOP 中执行方法):

    args(java.io.Serializable)

    请注意,此示例中给出的切入点与execution(* *(java.io.Serializable)). 如果在运行时传递的参数是 Serializable则args 版本匹配,如果方法签名声明了一个Serializable类型的参数,则执行版本匹配。

  • 目标对象具有 @Transactional注解的任何连接点(仅在 Spring AOP 中执行方法):

    @target(org.springframework.transaction.annotation.Transactional)
  • 目标对象的声明类型具有@Transactional注解的任何连接点(仅在 Spring AOP 中执行方法):

    @within(org.springframework.transaction.annotation.Transactional)
  • 执行方法具有 @Transactional注解的任何连接点(仅在 Spring AOP 中执行方法):

    @annotation(org.springframework.transaction.annotation.Transactional)
  • 任何接受单个参数的连接点(仅在 Spring AOP 中执行方法),并且传递的参数的运行时类型具有@Classified注解:

    @args(com.xyz.security.Classified)
  • Spring bean 上的任何连接点(方法仅在 Spring AOP 中执行)名为 tradeService:

    bean(tradeService)
  • 名称与*Service通配符表达式匹配的 Spring bean 上的任何连接点(仅在 Spring AOP 中执行方法):

    bean(*Service)

编写好的切入点

在编译期间,AspectJ 处理切入点以优化匹配性能。检查代码并确定每个连接点是否(静态或动态)匹配给定的切入点是一个代价高昂的过程。(动态匹配意味着无法从静态分析中完全确定匹配,并且在代码中放置测试以确定代码运行时是否存在实际匹配)。在第一次遇到切入点声明时,AspectJ 将其重写为匹配过程的最佳形式。这是什么意思?基本上,切入点在 DNF(析取范式)中被重写,切入点的组件被排序,以便首先检查那些评估成本较低的组件。

然而,AspectJ 只能使用它被告知的内容。为了获得最佳匹配性能,您应该考虑他们试图实现的目标,并在定义中尽可能缩小匹配的搜索空间。现有的指示符自然属于以下三组之一:kinded、scoping 和 contextual:

  • 种类指示符选择一种特定类型的连接点: execution、get、set、call和handler。

  • 范围指示符选择一组连接兴趣点(可能有多种):within和withincode

  • 上下文指示符根据上下文匹配(并且可以选择绑定): this、、target和@annotation

一个写得很好的切入点应该至少包括前两种类型(种类和范围)。您可以包含上下文指示符以根据连接点上下文进行匹配,或绑定该上下文以在通知中使用。由于额外的处理和分析,只提供一个 kinded 指示符或只提供一个上下文指示符是可行的,但可能会影响编织性能(使用的时间和内存)。范围指示符的匹配速度非常快,使用它们意味着 AspectJ 可以非常快速地消除不应进一步处理的连接点组。如果可能,一个好的切入点应始终包含一个切入点。

由于 Spring 的 AOP 框架基于代理的特性,根据定义,目标对象内的调用不会被拦截。对于 JDK 代理,只能拦截代理上的公共接口方法调用。使用 CGLIB,代理上的公共和受保护的方法调用被拦截(如果需要,甚至包可见的方法)。但是,通过代理的常见交互应始终通过公共签名进行设计。请注意,切入点定义通常与任何拦截的方法匹配。如果切入点严格来说是只公开的,即使在 CGLIB 代理场景中,通过代理进行潜在的非公开交互,也需要相应地定义它。如果您的拦截需求包括目标类中的方法调用甚至构造函数,请考虑使用 Spring 驱动的,而不是 Spring 的基于代理的 AOP 框架。这就构成了具有不同特点的不同AOP使用模式,所以在做决定之前一定要让自己熟悉编织。

<aop:config>和<aop:advisor>元素在基于中讨论。事务元素在中讨论。

除了返回类型模式(在ret-type-pattern前面的代码片段中)、名称模式和参数模式之外的所有部分都是可选的。返回类型模式确定方法的返回类型必须是什么才能匹配连接点。 *最常用作返回类型模式。它匹配任何返回类型。仅当方法返回给定类型时,完全限定的类型名称才匹配。名称模式与方法名称匹配。您可以将*通配符用作名称模式的全部或一部分。如果您指定声明类型模式,请包含一个尾随.以将其连接到名称模式组件。参数模式稍微复杂一些:()匹配不带参数的方法,而(..)匹配任意数量(零个或多个)的参数。该(*)模式匹配采用任何类型的一个参数的方法。 (*,String)匹配带有两个参数的方法。第一个可以是任何类型,而第二个必须是String. 有关更多信息,请参阅 AspectJ 编程指南的 部分。

this更常用于绑定形式。 有关如何使代理对象在通知正文中可用的信息, 请参阅

target更常用于绑定形式。有关如何使目标对象在通知正文中可用的信息, 请参阅

args更常用于绑定形式。请参阅部分,了解如何使方法参数在通知正文中可用。

您也可以@target在绑定表单中使用。有关如何使注解对象在通知正文中可用的信息, 请参阅

您也可以在绑定表单中使用@within。有关如何使注解对象在通知正文中可用的信息, 请参阅

您也可以在绑定表单中使用@annotation。有关如何使注解对象在通知正文中可用的信息, 请参阅

您也可以在绑定表单中使用@args。请参阅部分如何使注解对象在通知正文中可用。

AspectJ Programming Guide
AspectJ 5 Developer's Notebook
原生 AspectJ 编织
模式的 AOP 支持
事务管理
语言语义
声明通知部分。
声明通知部分。
声明通知
声明通知部分。
声明通知部分。
声明通知部分。
声明通知