猿创征文 第二季| #「笔耕不辍」--生命不息,写作不止# Spring AOP实现面向切面编程

62 阅读2分钟

定义

权限切面和日志切面穿插在软件模块中,为原始业务代码添加额外的拓展,随称为面向切面编程

AOP的做法是将通用、与业务无关的功能抽象封装为切面类

切面可配置在目标方法的执行、执行后运行,真正做到即插即用。

AOP的最终目的:在不修改源码的情况下对程序行为进行拓展

实现

1、引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.16</version>
    </dependency>
 
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.5</version>
    </dependency>
</dependencies>

2、模拟业务类
正常的一些dao/service


import org.springframework.stereotype.Component;

@Component
public class Say {

    public String saying(String s  ){
        return "=========: "+ s;
    }
}



3、定义Aspect切面类
主要开启切面、

package com.wasane.test1;

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

@Component
@Aspect
public class SayAop {

    @Pointcut("execution(public String com.study.test.Say.saying(..))")
    public void a (){

    }
    @Before("a()")
    public void before1(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        Object  [] args = joinPoint.getArgs();

        System.out.println(name+" before "+args[0]);
    }
    @After("a()")
    public void after1(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        Object [] args = joinPoint.getArgs();
        System.out.println(name+" after ,"+ args[0]);
    }

    @Around("a()")
    public void aroud1(ProceedingJoinPoint joinPoint) throws Throwable {
        String name = joinPoint.getSignature().getName();

        System.out.println(name+" aroud start");
        Object t =  joinPoint.proceed();
        System.out.println(name+" aroud return : "+ t);
        System.out.println(name+" aroud end");
    }



    @AfterReturning(value = "a()" , returning = "return2")
    public void return1(JoinPoint joinPoint , String return2){
        String name = joinPoint.getSignature().getName();

        System.out.println(name+"  return  :"+ return2 );
    }

    @AfterThrowing(value = "a()" , throwing = "excep")
    public void exception1(JoinPoint joinPoint , Exception excep){
        String name = joinPoint.getSignature().getName();

        System.out.println(name+"  Exception  :"+ excep );
    }

}



4、xml或这注解方法开启切面编程,因为spring是默认不开启的
在这里插入图片描述
或者

package com.wasane.test1;


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com....")
public class MyConfig {






}


5、测试



import com.wasane.test1.MyConfig;
import com.wasane.test1.Say;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyConfig.class})
public class AopTest {

    @Autowired
    Say s ;

    @Test
    public void test1(){
        System.out.println(s.saying(" gooos " ));
    }





}



AOP关键概念

注解back
Aspect切面
Target Class/Method目标类
PointCut切入点
JoinPoint连接点
Advice通知

Aspect类的方法名随意,返回参数为void/Object,但是参数必须为(JoinPoint joinPoint);

JoinPoint对象

joinPoint.getTarget();//从IOc容器内的目标对象
joinPoint.getSignature();//获取目标方法
joinPoint.getArgs();//获取目标

PointCut切点的execution()表达式

execution()表达式,规定Aspect表达式的应用类的范围

类修饰符public 返回值String 包范围-类名-方法名-方法的参数形式com.study.test.Say.saying(…)这个指的是saying方法所有参数形式都应用

@Pointcut("execution(public String com.study.test.Say.saying(..))")

Aspect的五种通知类型

Before Advice 前置通知 对应注解@Before
After Returning Advice 返回后通知
After Throwing Advice 异常通知
After Advice 后置通知
Around Advice环绕通知,最强大通知,自定义通知执行时机,可决定目标方法是否运行

实现原理

Spring基于代理模式实现功能动态拓展AOP,包含两种形式:
1.目标类有接口,通过JDK动态代理实现功能拓展
2.目标类没有接口,通过CGLib组件实现功能拓展

CGLib

CGLib是运行时字节码增强技术

Spring AOP拓展无接口类使用CGLib

AOP会运行时生成目标继承类字节码的方式进行行为拓展

本文使用 文章同步助手 同步