网站建设公司前景,商丘关键词优化推广,传媒在线网站模板,wordpress 模板兔Spring AOP是Spring框架中的一个模块#xff0c;它允许开发人员使用面向切面编程(AOP)的思想来解耦系统的不同层次。 Spring AOP的核心概念是切面(aspect)、连接点(join point)、通知(advice)、切点(pointcut)和引入(introduction)。 切面(aspect)#xff1a;切面是一个类, 它…Spring AOP是Spring框架中的一个模块它允许开发人员使用面向切面编程(AOP)的思想来解耦系统的不同层次。 Spring AOP的核心概念是切面(aspect)、连接点(join point)、通知(advice)、切点(pointcut)和引入(introduction)。 切面(aspect)切面是一个类, 它包含了通知(advice)和切点(pointcut)。连接点(join point)在AOP中连接点是程序执行的某个时间点例如方法调用、异常抛出、对象实例化等。通知(advice)在连接点上执行的代码片段它们包括before、after、afterReturning、afterThrowing和around五种类型。切点(pointcut)在程序执行时选择哪些连接点执行通知的表达式例如execution(* com.example.demo.*(..))表示匹配com.example.demo包下的任意方法。引入(introduction)在不修改现有类代码的情况下向现有类添加新方法或属性。
Spring AOP底层使用动态代理和字节码生成来实现。切面由通知和切点组成连接点是程序执行的某个时间点切点根据表达式匹配连接点通知是在连接点上执行的代码片段在方法调用前或调用后执行某些操作。
Spring AOP的优点是可以通过配置实现解耦不用修改经常变动的业务逻辑代码而且可以重用通知降低代码冗余程度。
以下是一个使用Spring Boot AOP实现日志记录的例子
1.创建一个Spring Boot项目并添加如下依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId
/dependency
2.定义一个UserService接口和一个实现类UserServiceImpl实现类中包含一个方法getUserById
public interface UserService {User getUserById(long id);
}Service
public class UserServiceImpl implements UserService {Overridepublic User getUserById(long id) {System.out.println(调用getUserById方法id id);return new User(id, 张三);}
}
3.定义一个切面LogAspect
使用注解Aspect标识切面
使用Pointcut定义切点
使用
Before、
After、
AfterReturning、
AfterThrowing、
Around注解定义通知
Aspect
Component
public class LogAspect {Pointcut(execution(* com.example.demo.service.UserService.*(..)))public void userServicePointcut() {}Before(userServicePointcut())public void before(JoinPoint joinPoint) {System.out.println(调用 joinPoint.getSignature().getName() 方法);}AfterReturning(pointcut userServicePointcut(), returning result)public void afterReturning(JoinPoint joinPoint, Object result) {System.out.println(调用 joinPoint.getSignature().getName() 方法完成返回值 result);}AfterThrowing(pointcut userServicePointcut(), throwing exception)public void afterThrowing(JoinPoint joinPoint, Exception exception) {System.out.println(调用 joinPoint.getSignature().getName() 方法出现异常异常信息 exception.getMessage());}
} 在上面的切面中我们使用Pointcut注解定义切点使用Before、AfterReturning、AfterThrowing等注解定义通知在通知中使用JoinPoint获取方法签名、参数等信息输出日志。
4.运行应用程序并测试
RestController
public class UserController {Autowiredprivate UserService userService;GetMapping(/user/{id})public User getUser(PathVariable long id) {return userService.getUserById(id);}
}
在控制台中可以看到如下输出
调用getUserById方法id1
调用getUserById方法完成返回值User [id1, name张三]
匹配方法
Pointcut是基于表达式的描述符用于指定应该在哪些方法上执行通知。Pointcut表达式可以使用AspectJ的语法也可以使用Spring AOP的语法。
以下是常用的Pointcut表达式
execution使用该表达式匹配方法执行的切点。 execution(public * com.example.demo.service.UserService.*(..))匹配com.example.demo.service.UserService类中所有public修饰符的方法。 execution(* com.example.demo.service..(..))匹配com.example.demo.service包下所有类的任意方法。 execution(* com.example.demo.service...(..))匹配com.example.demo.service包以及其子包下所有类的任意方法。
within使用该表达式匹配指定类型的切点包括该类型的子类型。 within(com.example.demo.service.*)匹配所有com.example.demo.service包中的类型。 within(com.example.demo.service..*)匹配com.example.demo.service包以及其子包中的所有类型。
annotation使用该表达式匹配带有指定注解的切点。 annotation(org.springframework.web.bind.annotation.RequestMapping)匹配带有RequestMapping注解的方法。 within(org.springframework.stereotype.Service)匹配带有Service注解的类中的所有方法。
args使用该表达式匹配带有指定参数类型的切点。 args(java.lang.String)匹配一个参数类型为String的方法。 args(java.lang.String, ...)匹配至少一个参数类型为String的方法。
bean使用该表达式匹配指定名称或类型的bean的切点。 bean(userService)匹配名称为userService的bean。 bean(userService*)匹配名称以userService开头的bean。
除了以上的表达式外还有很多其他的表达式可以根据具体的需求选择使用。需要注意的是在使用Pointcut表达式时需要注意匹配的粒度匹配过于精确会导致无法匹配到需要的切点匹配过于宽泛则会匹配到不需要的切点。