AOP的运用

本文深入解析了面向切面编程(AOP)的概念及其在Spring框架中的应用,包括AOP的基本术语、应用场景以及如何使用Spring AOP进行日志记录和性能监控。同时,文章对比了静态代理和动态代理的不同,详细介绍了如何通过Spring配置文件实现AOP,以及如何编写日志通知类和性能统计功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、AOP来也

1、概念

  • 面向切面编程(Aspect Oriented Programming)
  • 跨模块的代码共享
  • 面向对象编程的一种补充,用于处理一些具有横切性质的系统级服务

2、名词必备

  • 切面Aspect 切面编程的完整定义模块,比如日志切面
  • 连接点Join point  能够植入切面的部分,比如方法前后,抛出异常时都
  • 通知Advice 要对切面添加的功能代码,比如 安全,事物,日志等功能代码
  • 切入点Pointcut 指定具体的拦截地点。可以通过spEL指定连接点
  • 引入Introduction 对目标类添加新方法及属性
  • 目标对象Target objec 被切面切的对象
  • 代理proxy 实现AOP的一种原理
  • 织入Weaving 把切面应用到目标对象来创建新的代理对象的过程

3、应用场景

  • 权限验证

  • 性能追踪

  • 日志追踪

  • 懒加载

二、AOP代理

1、代理

  • 静态代理(Static Proxy) 由程序员创建或特定工具自动生成源代码,再对其编译
    • 如果接口加一个方法,所有的实现类和代理类里都需要做个实现
    • 增加了代码的复杂度
    • 动态代理就可以避免这个缺点
  • 动态代理(Dynamic Proxy) 在程序运行时,运用反射机制动态创建而成。
    • 动态代理类只能代理接口
    • 代理类都需要实现InvocationHandler类,实现invoke方法
    • 该invoke方法就是调用被代理接口的所有方法时需要调用
    • 该invoke方法返回的值是被代理接口的一个实现类

2、AOP实现

  • pox.xml配置springframework、aspectj、aspectj
<!--    spring aop支持包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>${aspectj.version}</version>
    </dependency>

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>${aspectj.version}</version>
    </dependency>
  • 建立LogAdvice类,写日志通知类和性能统计
阿package com.chinasoft.spring.skillpig.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 日志通知类
 */
@Component
public class LogAdvice {
    public void logBefore(JoinPoint joinPoint){
        String builder = getFullMethodButcher(joinPoint);
        System.out.println(builder);
    }

    private String  getFullMethodButcher(JoinPoint joinPoint) {
        StringBuilder builder=new StringBuilder();
        //从切入点获取类名
        builder.append(joinPoint.getTarget().getClass().getCanonicalName());
        builder.append("#");
        //从切入点获取方法名
        builder.append(joinPoint.getSignature().getName());
        builder.append("#");
        //获取方法参数
        builder.append(Arrays.toString(joinPoint.getArgs()));
        return builder.toString();
    }

    /**
     * 性能统计
     * @param pjp
     * @return
     */
    public Object performanceStat(ProceedingJoinPoint pjp){
        String butcher=getFullMethodButcher(pjp);
        Object result=null;
        try {
            //方法执行前时间
            long before=System.currentTimeMillis();
            //执行方法
            Object[] args=pjp.getArgs();
            boolean warnFlag=false;
            for (Object arg:args){
                if (arg instanceof String){
                    String s=(String)arg;
                    if (s.contains(("李"))){
                        warnFlag=true;
                        System.err.println("不是整形Integer");
                        break;
                    }
                }
            }
            if (!warnFlag){
                //执行该方法
                result=pjp.proceed();
            }else {
                return null;
            }
            //执行方法后
            long after=System.currentTimeMillis();
            System.out.println(butcher+"耗时, "+(after-before)+"毫秒");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return butcher;
    }
}
  • 建立KillPigService接口,并有一个订单方法
package com.chinasoft.spring.skillpig.aop.services;

public interface KillPigServices {

    /**
     * 杀猪预定方法
     * @param pigCount 有几头待宰大猪
      * @return
     */
    String order(int pigCount);
}
  • 建立KillPigServiceImpl类,实现KillPigService接口
package com.chinasoft.spring.skillpig.aop.services.impl;

import com.chinasoft.spring.skillpig.aop.services.KillPigServices;
import org.springframework.stereotype.Component;

@Component("killPigServicesImpl")
public class KillPigServicesImpl implements KillPigServices {
    @Override
    public String order(int pigCount) {
        System.out.println("预定杀肥猪订单方法中。。。。");
        String s=null;
        for(int i=0;i<10000;i++){
            s+=i;
        }
        return null;
    }
}

三、代理实现

1、静态代理

  • 一个接口,两个实现类
  • 一个原始类,一个代理类

2、代理实现

  • 建立KillPigService接口,写kill方法
package com.chinasoft.spring.skillpig.proxy;

public interface KillPigService {
    double kill(String pigname);

}
  • 建立原始类KillPigServiceImpl,实现KillService接口
package com.chinasoft.spring.skillpig.proxy;

public class KillPigServiceImpl implements KillPigService {
    @Override
    public double kill(String pigname) {
        System.out.println("屠宰"+pigname);
        return 1000;
    }
}
  • 建立代理类,实现KillPigImplProxy接口
package com.chinasoft.spring.skillpig.proxy;

public class KillPigServiceImplProxy implements KillPigService {

    private KillPigServiceImpl killPigServiceImpl=new KillPigServiceImpl();
    @Override
    public double kill(String pigname) {
        System.out.println("执行KillPigServiceImpl方法"+pigname);

        //方法执行前时间
        long before=System.currentTimeMillis();
        double result=killPigServiceImpl.kill(pigname);
        //方法执行后时间
        long after=System.currentTimeMillis();

        System.out.println("执行killPigServiceImpl方法结束,耗时:"+(after-before)+"毫秒");
        return result;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值