• 【JAVA笔记——器】Spring面向切面编程 Aspect Oriented Programming with Spring


    并非完全按照Reference翻译,有删改
    原文 Aspect Oriented Programming with Spring

    AOP术语

    通知Advice
    切面的工作为通知
    SPRING 五种通知
    before after after-returning after-throwing around

    连接点 Joinpoint
    连接点是执行过程中能够插入切面的一个点

    切点 Pointcut
    并非所有连接点都需要被通知,切点定义匹配通知所要织入的一个多或多个连接点

    切面 Aspect
    切面是通知和切点的结合。定义切面的如何实现

    引入 Inteoduction
    引入允许我们向现有的类添加新方法或属性

    织入 Weaving
    织入是将切面应用到目标对象创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。目标对象的生命周期有多个点可以织入

    • 编译期
    • 类加载期
    • 运行期

    配置

    @Aspect

    Aspect注解切面对象

    package org.xyz;
    import org.aspectj.lang.annotation.Aspect;
    
    @Aspect
    public class NotVeryUsefulAspect {
    
    }
    

    切点

    AspectJ包含的不支持
    call, get, set, preinitialization, staticinitialization, initialization, handler, adviceexecution, withincode, cflow, cflowbelow, if, @this, and @withincode
    使用报出IllegalArgumentException

    execution - 连接点匹配方法,这是在Sring AOP主要的使用的切点设计器
    within - 限制匹配连接点在特定类型,相当于简化的execution方法
    this - 限制匹配连接点所对应Bean引用是特定类型
    args - 限制匹配连接点的参数列表是特定类型
    @target - 限制匹配连接点对应的类的对象拥有所标记的的类型
    @args - 限制匹配连接点对应的类运行时参数是所标记的类型
    @within - 限制匹配连接点在标注的类中
    @annotation - 限制匹配连接点,连接点的主体被注解
    

    execution - for matching method execution join points, this is the primary pointcut designator you will use when working with Spring AOP

    within - limits matching to join points within certain types (simply the execution of a method declared within a matching type when using Spring AOP)

    this - limits matching to join points (the execution of methods when using Spring AOP) where the bean reference (Spring AOP proxy) is an instance of the given type

    target - limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type

    args - limits matching to join points (the execution of methods when using Spring AOP) where the arguments are instances of the given types

    @target - limits matching to join points (the execution of methods when using Spring AOP) where the class of the executing object has an annotation of the given type

    @args - limits matching to join points (the execution of methods when using Spring AOP) where the runtime type of the actual arguments passed have annotations of the given type(s)

    @within - limits matching to join points within types that have the given annotation (the execution of methods declared in types with the given annotation when using Spring AOP)

    @annotation - limits matching to join points where the subject of the join point (method being executed in Spring AOP) has the given annotation

    原生Spring AOP基于代理(无论是JDK Proxy/CGLIB),均无法对可访问性小于protected的类进行代理。
    如果需要,可以使用Spring-driven native AspectJ weaving

    Spring AOP支持PCD命名Bean,idOrNameOfBean支持* , &&, ||

    bean(idOrNameOfBean)
    

    Demo

    @Pointcut("execution(public * *(..))")
    private void anyPublicOperation() {}
    
    @Pointcut("within(com.xyz.someapp.trading..*)")
    private void inTrading() {}
    
    @Pointcut("anyPublicOperation() && inTrading()")
    private void tradingOperation() {}
    

    官方提供公共配置

    package com.xyz.someapp;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class SystemArchitecture {
    
        /**
         * A join point is in the web layer if the method is defined
         * in a type in the com.xyz.someapp.web package or any sub-package
         * under that.
         */
        @Pointcut("within(com.xyz.someapp.web..*)")
        public void inWebLayer() {}
    
        /**
         * A join point is in the service layer if the method is defined
         * in a type in the com.xyz.someapp.service package or any sub-package
         * under that.
         */
        @Pointcut("within(com.xyz.someapp.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.someapp.dao package or any sub-package
         * under that.
         */
        @Pointcut("within(com.xyz.someapp.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.someapp.abc.service and com.xyz.someapp.def.service) then
         * the pointcut expression "execution(* com.xyz.someapp..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.someapp..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.someapp.dao.*.*(..))")
        public void dataAccessOperation() {}
    
    }
    

    匹配规则

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

    ret-type-pattern | name-pattern | param-pattern必选,其他可选

    modifiers-pattern 修饰语匹配 : public *匹配任意类型
    ret-type-pattern 返回类型匹配 : Object *匹配任意类型
    declaring-type-pattern 定义类型匹配 : com.cunchen.entity.Test *匹配任意类型
    name-pattern 方法名匹配 : testMethod *匹配任意方法
    param-pattern 参数匹配 : Object | ()无参数 | (..)任意参数 | ()任意一个参数 | ( , String) 任意一个参数 + 一个String参数

    //匹配public方法
    execution(public * *(..))
    
    //匹配开始名称set
    execution(* set*(..))
    
    //匹配AccountService的子类实现方法
    execution(* com.xyz.service.AccountService.*(..))
    
    //匹配com.xyz.servic包下接口的子类实现方法
    execution(* com.xyz.service.*.*(..))
    
    //在com.xyz.service包中的任意连接点
    within(com.xyz.service.*)
    
    //在com.xyz.service包以及子包中的任意连接点
    within(com.xyz.service..*)
    
    //代理接口AccountService的任意连接点
    this(com.xyz.service.AccountService)
    
    //任意实现AccountService接口实现对象的连接点
    target(com.xyz.service.AccountService)
    
    //任意只有一个参数,且参数在运行时是Serializable的任意连接点
    args(java.io.Serializable)
    
    //任意目标对象被注解为@Transactional的连接点
    @target(org.springframework.transaction.annotation.Transactional)
    
    //任意目标对象的声明中拥有@Transactional
    @within(org.springframework.transaction.annotation.Transactional)
    
    //任意连接点被注释@Transactional
    @annotation(org.springframework.transaction.annotation.Transactional)
    
    //任意连接点,它接受一个参数,并且传入的参数的运行时类型有@Classified注解
    @args(com.xyz.security.Classified)
    
    //任意 Spring bean 命名为 tradeService 的连接点
    bean(tradeService)
    
    //任意 Spring bean 符合通配符统配为 *Service 的连接点
    bean(*Service)
    
  • 相关阅读:
    熬夜的朋友看一看 [转]
    配置ubuntu
    C++string类常用函数 (转)
    ArcGIS Engine栅格数据使用总结 (转)
    fstream的用法+代码
    [转] 英语飙升的好方法
    MFC 非模态对话框(转)
    十九个国内外主流的三维GIS软件(转)
    Google C++ 风格指南 中文版
    std::set用法(转)
  • 原文地址:https://www.cnblogs.com/cunchen/p/9464135.html
Copyright © 2020-2023  润新知