[Spring 04] AOP三种实现方式


Spring_04 AOP


5. AOP

1. AOP在Spring中的作用

允许用户自定义切面, 提供声明式事务

横切关注点: 跨越应用程序多个模块的方法和功能(与业务逻辑无关)如日志,安全,缓存,事务

ASPECT 切面: 横切关注点 被模块化的的对象(如Log类)

Advice 通知: 切面需要完成的工作 Log中的一个方法

Target 目标: 被通知的对象

Proxy 代理: 向目标对象应用 通知 ,之后创建的对象

PointCut 切入点: 切面通知 执行的“地点”的定义

JointPoint 连接点: 与切入点匹配的执行点

Advice类型:

MethodBeforeAdvice, AfterReturningAdvice, MethodInterceptor, ThrowsAdvice, IntroductionInterceptor

前置通知, 后置通知, 环绕通知, 异常抛出通知, 引介通知

AOP在不改变原有代码的方式下,增加新功能

导入maven包:

aspectjweaver: 织入包

2. Spring API接口实现AOP

写好怎删改查的接口和实现类: UserService和UserServiceImpl

写Log类:

public class BeforeLog implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName()+"类的"+method.getName()+"被执行了");
    }
}

在beans.xml中注册:

<?xml version="1.0" encoding="UTF-8"?>

    
    
    

    
        
        
        
    

  • 头文件中添加aop约束

  • aop标签中添加两个元素: 切入点通知

  • 测试类中正常调用

其中,切入点的expression是一个表达式,固定为: *表示通配符,..表示任意参数

execution(要执行的位置! (*(修饰词) *(返回值) *(类名) *(方法名) *(参数)))

3. 切面定义实现AOP

缺点:过程中无法添加和上述方法一样的,对业务类的交互(通过反射获取名称等)

写Aspect切面类: 其中包含 Advice通知;对于这部分的定义在xml文件中才说明。

public class AspectLog {
    public void before(){
        System.out.println("before");
    }
    public void after(){
        System.out.println("after");
    }
}

xml文件中,先注册AspectLog的bean,再定义切面:


    定义切面(定义切入点,定义通知
        
        
        
    

4. 注解实现AOP

Aspect类:(注解不要导错包,都是Aspectj下的)

@Aspect
public class AnnotationLog {
    @Before("execution(* com.roy.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("before");
    }
    @After("execution(* com.roy.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("after");
    }
    @Around("execution(* com.roy.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint pj) throws Throwable {
        System.out.println("around_Before");
        pj.proceed();//表示在这里执行业务的方法
        System.out.println("around_After");
    }
}

ProceedingJointPoint类:可以通过这个类实现第二种方式中无法和业务类交互的东西:

如: .proced()表示指定业务类实现的位置

.getSignature()表示获取在业务类中正在执行的方法名

.get*, 可以获得更多信息

xml中注册: (注意添加对aspect注解的支持





Spring中动态代理的实现方式:

基于接口的JDK,和基于类的cgLib

时,(默认为false, 使用JDK产生代理类

时,使用cgLib产生代理类

区别: (存疑)实测目标类没有接口,都能实现

  • 当被代理类是通过接口实现的,则用JDK(通过动态代理实现);

  • 当被代理类是一个类, CGLIB通过字节码生成子类,继承被代理类来实现代理。


Spring5版本对around、before、after的执行顺序:

around_Before 环绕
before
方法执行
afterReturning
after
around_After 环绕