1、通知
目标对象:
package com.sgcc.lms.aop;@Component("calc")public class CalcImpl implements Calc {@Overridepublic int add(int i, int y) {int result = i + y;return result;}@Overridepublic int sub(int i, int y) {int result = i - y;return result;}@Overridepublic int mul(int i, int y) {int result = i * y;return result;}@Overridepublic int div(int i, int y) {int result = i / y;return result;}}
切面:
package com.sgcc.lms.aop;import java.util.Arrays;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;/*** 可以使用 @Order 注解指定切面的优先级, 值越小优先级越高*/@Order(2)@Aspect@Componentpublic class LoggingAspect {/*** 定义一个方法, 用于声明切入点表达式. 一般地, 该方法中再不需要添入其他的代码.* 使用 @Pointcut 来声明切入点表达式.* 后面的其他通知直接使用方法名来引用当前的切入点表达式.*/@Pointcut("execution(public int com.sgcc.lms.aop.Calc.*(..))")public void declareJointPointExpression(){}/*** 在 com.atguigu.spring.aop.ArithmeticCalculator 接口的每一个实现类的每一个方法开始之前执行一段代码*/@Before("declareJointPointExpression()")public void beforeMethod(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();Object [] args = joinPoint.getArgs();System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));}/*** 在方法执行之后执行的代码. 无论该方法是否出现异常*/@After("declareJointPointExpression()")public void afterMethod(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("The method " + methodName + " ends");}/*** 在方法法正常结束受执行的代码* 返回通知是可以访问到方法的返回值的!*/@AfterReturning(value="declareJointPointExpression()",returning="result")public void afterReturning(JoinPoint joinPoint, Object result){String methodName = joinPoint.getSignature().getName();System.out.println("The method " + methodName + " ends with " + result);}/*** 在目标方法出现异常时会执行的代码.* 可以访问到异常对象; 且可以指定在出现特定异常时在执行通知代码*/@AfterThrowing(value="declareJointPointExpression()",throwing="e")public void afterThrowing(JoinPoint joinPoint, Exception e){String methodName = joinPoint.getSignature().getName();System.out.println("The method " + methodName + " occurs excetion:" + e);}/*** 环绕通知需要携带 ProceedingJoinPoint 类型的参数.* 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法.* 且环绕通知必须有返回值, 返回值即为目标方法的返回值*//*@Around("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")public Object aroundMethod(ProceedingJoinPoint pjd){Object result = null;String methodName = pjd.getSignature().getName();try {//前置通知System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));//执行目标方法result = pjd.proceed();//返回通知System.out.println("The method " + methodName + " ends with " + result);} catch (Throwable e) {//异常通知System.out.println("The method " + methodName + " occurs exception:" + e);throw new RuntimeException(e);}//后置通知System.out.println("The method " + methodName + " ends");return result;}*/}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"><!-- <bean id="calc" class="com.sgcc.lms.aop.CalcImpl"></bean> --><!-- 配置自动扫描的包 --><context:component-scanbase-package="com.sgcc.lms.aop"></context:component-scan><!-- 配置自动为匹配 aspectJ 注解的 Java 类生成代理对象 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>
使用
package com.sgcc.lms.aop;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");Calc calc = (Calc) ctx.getBean("calc");System.out.println(calc.getClass().getName());int result = calc.add(1, 2);System.out.println("result:" + result);result = calc.div(1000, 10);System.out.println("result:" + result);}}
依赖
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${springframework.version}</version></dependency></dependencies>
2、spring boot使用注解记录方法耗时

package com.kd.ndmp.dc.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** @Author 李孟帅* @Date 2021/8/13* @Description TODO 方法耗时注解*/@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface TakeTime {String value() default "";}
环绕通知
package com.kd.ndmp.dc.aspect;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;import java.time.Duration;import java.time.LocalDateTime;/*** @Author 李孟帅* @Date 2021/8/13* @Description TODO*/@Aspect@Slf4j@Componentpublic class TakeTimeAspect {private static final String LINE = "==========================================》{}";@Pointcut("@annotation(com.kd.ndmp.dc.annotation.TakeTime)")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) {Object result = null;try {LocalDateTime now = LocalDateTime.now();result = joinPoint.proceed();Duration between = Duration.between(now, LocalDateTime.now());log.info("耗时:{}",between.toMillis());} catch (Throwable throwable) {throwable.printStackTrace();}return result;}}
使用

注意
使用注解的,该类需要通过spirng ioc容器的bean 管理
