侧边栏壁纸
博主头像
Shawe`Blog博主等级

正确的思维是创造一切的前提。

  • 累计撰写 33 篇文章
  • 累计创建 4 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Spring之面向切面编程

什么是Spring AOP?

是一种基于动态代理技术的面向切面的编程思想。

动态代理是怎样实现的?

利用反射或者字节码操作,在运行的时候生成代理类和对象,实现在不修改原始类的情况下增强功能。必要的参数有 需要代理的类或接口、执行的目标方法、执行方法所需要的入参。

第一步:根据传入的对象反射出一个代理对象

第二步:根据需要执行的目标方法入参定位到需要增强的方法

第三步:把方法入参交给代理对象需要执行的目标方法,执行增强方法,返回出参

JDK动态代理和CJLB动态代理的区别是什么?

JDK动态代理是基于接口的代理,而CGLIB动态代理是基于继承的代理。通常情况下,如果你的目标类实现了接口,你可以使用JDK动态代理;如果目标类没有实现接口,你可以使用CGLIB动态代理。

AOP和OOP有什么区别呢?

AOP是面向切面编程,关注横切关注点,如日志记录、事务管理等。OOP是面向对象编程,更多的是关注对象及其之间的交互,如封装继承多态等。

AOP有哪些常用术语?

切面:业务增强逻辑和原有逻辑交界的地方

织入:把增强逻辑插入到原有逻辑前的动作

连接点:需要增强的原有逻辑方法

切入点:切面具体织入的位置

通知:增强的逻辑部分

目标对象:需要增强的对象

代理对象:帮助原有对象完成增强逻辑的对象

Spring中AOP有哪几种实现方式?

1.通过创建代理对象实现AOP,根据接口的JDK动态代理或者基于继承的CJLB动态代理,如根据接口的示例如下:

public interface Calculator {

    int add(int a, int b);

}

public class CalculatorImpl implements Calculator {

    @Override

    public int add(int a, int b) {

        System.out.println("Adding " + a + " and " + b);

        return a + b;

    }

}

public class LoggingAspect {

    public void beforeAdd(JoinPoint joinPoint) {

        Object[] args = joinPoint.getArgs();

        System.out.println("Before adding: " + args[0] + " and " + args[1]);

    }

    public void afterAdd(JoinPoint joinPoint, int result) {

        System.out.println("After adding: result is " + result);

    }

}

<bean id="calculator" class="com.example.CalculatorImpl"/>

<bean id="loggingAspect" class="com.example.LoggingAspect"/>

<aop:config>

    <aop:aspect ref="loggingAspect">

        <aop:pointcut id="addMethod" expression="execution(* com.example.Calculator.add(..))"/>

        <aop:before method="beforeAdd" pointcut-ref="addMethod"/>

        <aop:after-returning method="afterAdd" returning="result" pointcut-ref="addMethod"/>

    </aop:aspect>

</aop:config>

2.通过AspectJ实现AOP,AspectJ是一个独立的AOP框架,能够支持注解或者配置文件xml的方式来增强Spring的代理能力,有丰富的切入点表达式等。使用示例如下:

@Aspect

public class LoggingAspect {

    @Before("execution(* com.example.Calculator.add(..))")

    public void beforeAdd(JoinPoint joinPoint) {

        Object[] args = joinPoint.getArgs();

        System.out.println("Before adding: " + args[0] + " and " + args[1]);

    }

    @AfterReturning(pointcut = "execution(* com.example.Calculator.add(..))", returning = "result")

    public void afterAdd(JoinPoint joinPoint, int result) {

        System.out.println("After adding: result is " + result);

    }

}

Spring AOP有哪些常用注解?

@Aspect:用于定义切面(Aspect)。

@Before:在目标方法执行之前执行通知(Advice)。

@After:在目标方法执行之后(无论是否发生异常)执行通知。

@AfterReturning:在目标方法正常返回后执行通知,可以访问方法的返回值。

@AfterThrowing:在目标方法抛出异常后执行通知,可以访问到抛出的异常。

@Around:可以在方法调用之前和之后执行通知,可以控制方法的执行流程,包括是否执行目标方法。

@Pointcut:定义切点(Pointcut),用于指定切入点表达式。

AspectJ的切入点表达式是什么规则?

符号

意义

*

0至多个字符

..

方法参数中表示任意多个参数,用在包名后表示当前包及其子包路径

+

用在类名后表示当前类及子类,用在接口后表示接口及实现类

Execution(执行表达式)

Execution 是最常用的连接点。它匹配方法的执行,语法形式为 execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)。

其中 modifiers-pattern 匹配修饰符,ret-type-pattern 匹配返回类型,declaring-type-pattern 匹配声明类型,name-pattern 匹配方法名,param-pattern 匹配参数,throws-pattern 匹配异常。

// 匹配返回类型为String的UserService类中的所有方法
execution(String com.example.service.UserService.*(..))

// 匹配任意参数且返回类型为void的任意方法
execution(void *(..))

// 匹配在com.example.service包及其子包下的所有方法
execution(* com.example.service..*(..))
Within(类型表达式)

Within 匹配某个类型内的所有方法执行。语法形式为 within(package-name-pattern?) 或者 withincode(method-pattern)。

// 匹配com.example.service包及其子包下的所有方法
within(com.example.service.*)

// 匹配UserService类内的所有方法
within(com.example.service.UserService)
This 和 Target(目标对象表达式)

This 匹配当前执行对象的类型。

Target 匹配当前执行对象的目标对象类型。

// 匹配当前执行对象为UserService类型的方法
this(com.example.service.UserService)

// 匹配目标对象类型为UserService的方法
target(com.example.service.UserService)
Args(参数表达式)

Args 匹配传入方法的参数类型。语法形式为 args(type-pattern)。

// 匹配参数类型为String的方法
args(String)

// 匹配参数类型为int和String的方法
args(int, String)
@annotation(注解表达式)

@annotation 匹配带有特定注解的方法。语法形式为 @annotation(annotation-type-pattern)。

// 匹配使用@Transactional注解的方法
@annotation(org.springframework.transaction.annotation.Transactional)
@within 和 @target(注解目标表达式)

@within 匹配包含特定注解的类型。

// 匹配类上标注有@Service注解的方法
@within(org.springframework.stereotype.Service)

// 匹配目标对象类型上标注有@Service注解的方法
@target(org.springframework.stereotype.Service)
if(条件表达式)

if 条件表达式可以添加额外的条件来限制匹配。

// 匹配返回类型为String且方法名以"get"开头的方法,且参数类型不为null
execution(String get*(..)) && args(!null)
Pointcut 组合

切入点表达式可以通过 &&(逻辑与)、||(逻辑或)和 !(逻辑非)等逻辑操作符进行组合。

// 匹配声明类型为UserService的所有方法,并且方法名以"get"开头或者参数类型为String
within(com.example.service.UserService) && (execution(* get*(..)) || args(String))

0

评论区