spring aop

aop 入门

  • 导入相关坐标
  • 在业务层抽取通用代码
  • 把通知加入 spring 容器管理
  • 在配置文件中配置 aop 的配置

aop 案例

application.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/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 开启 aop 注解驱动 -->
    <aop:aspectj-autoproxy/>

    <!-- 开启 spring 注解驱动-->
    <context:component-scan base-package="com.asaawan"/>

    <!-- 抽取的功能要配置成 spring 控制的资源-->
    <bean id="accountAdvice" class="com.asaawan.aop.AccountAdvice"/>

    <!-- aop 配置 -->
    <aop:config>
        <!--配置公共切入点-->
        <aop:pointcut id="pc" expression="execution(* com.asaawan.service.*Service.*(..))"/>
        <!--配置切面-->
        <aop:aspect id="aspect" ref="accountAdvice">
            <!--配置局部切入点-->
            <!--<aop:pointcut id="pt" expression="execution(* *(..))"/>-->
            
            <!--直接配置切入点-->
            <!--<aop:before method="runtimeAround" pointcut="execution(* *(..))"/>-->
            
            <!--通知与切入点之间的关系-->
            <aop:around method="runtimeAround" pointcut-ref="pc"/>
        </aop:aspect>
    </aop:config>
</beans>

AccountAspect 配置

public class AccountAspect {

    public Object runtimeAround(ProceedingJoinPoint pjp) throws Throwable {
        //获取执行签名信息
        Signature signature = pjp.getSignature();
        //通过签名获取执行类型(接口名)
        String className = signature.getDeclaringTypeName();
        //通过签名获取执行操作名称(方法名)
        String methodName = signature.getName();

        //执行时长累计值
        long sum = 0L;
        Object proceed = null;

        for (int i = 0; i < 10000; i++) {
            //获取操作前系统时间 startTime
            long startTime = System.currentTimeMillis();
            //原始操作调用
            proceed = pjp.proceed(pjp.getArgs());
            //获取操作后系统时间 endTime
            long endTime = System.currentTimeMillis();
            sum += endTime - startTime;
        }

        //打印信息
        System.out.println(className + ":" + methodName + "   (万次)run:" + sum + "ms");
        
        //返回结果
        return proceed;
    }
}

AccountAspect 注解

@Component
@Aspect
public class AccountAspect {

    @Pointcut("execution(* com.asaawan.service.*Service.*(..))")
    public void pointcut(){}

    @Around("pointcut()")
    public Object runtimeAround(ProceedingJoinPoint pjp) throws Throwable {
        //获取执行签名信息
        Signature signature = pjp.getSignature();
        //通过签名获取执行类型(接口名)
        String className = signature.getDeclaringTypeName();
        //通过签名获取执行操作名称(方法名)
        String methodName = signature.getName();

        //执行时长累计值
        long sum = 0L;
        Object proceed = null;

        for (int i = 0; i < 10000; i++) {
            //获取操作前系统时间 startTime
            long startTime = System.currentTimeMillis();
            //原始操作调用
            proceed = pjp.proceed(pjp.getArgs());
            //获取操作后系统时间 endTime
            long endTime = System.currentTimeMillis();
            sum += endTime - startTime;
        }

        //打印信息
        System.out.println(className + ":" + methodName + "   (万次)run:" + sum + "ms");
        return proceed;
    }
}

常见通知类型注解

  • @Before
  • @After
  • @AfterReturning
  • @AfterThrowing
  • @Around
posted @ 2021-06-17 20:29  山奈  阅读(70)  评论(0)    收藏  举报