SpringAOP实现

1、导入依赖

XML 复制代码
        <!--SpringAOP的织入包-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.19</version>
        </dependency>

2、创建AppConfig配置类

复制代码
@Configuration:配置类注解,使用该注解的类为一个配置类,其中用于定义交给Spring管理的各个方法@ComponentScan("com.jiazhong.dao.impl"):组件扫描器注解
    - 该注解会自动扫描指定包中的所有类,并将扫描到的类中带有@Component注解的类管理起来
java 复制代码
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration //配置注解
@ComponentScan({"com.jiazhong.service","com.jiazhong.aspects"}) //组件扫描器注解
//@ComponentScan("com.jiazhong") 扫描com.jiazhong包下的所有类
public class AppConfig {
}

3、创建UserService接口及其实现类UserServiceImpl

java 复制代码
public interface UserService {
    void add();
    void queryAll();
    String queryByName(String name);
    void del(int id);
}
复制代码
@Service("userService"):Spring的服务层对象注解,它和@Component注解功能一样,只是语义更加明确
    - 在Service层使用该注解
java 复制代码
import com.jiazhong.service.UserService;
import org.springframework.stereotype.Service;

@Service("userService") //Spring的服务层对象注解,@Component注解功能一样
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("执行UserServiceImpl---->add方法......");
    }

    @Override
    public void queryAll() {
        System.out.println("执行UserServiceImpl---->queryAll方法......");
    }

    @Override
    public String queryByName(String name) {
        System.out.println("执行UserServiceImpl---->queryByName方法......");
        //throw new RuntimeException();
        return "java"+name;
    }

    @Override
    public void del(int id) {
        System.out.println("执行UserServiceImpl---->del方法......");
    }
}

4、创建切面类MyAspect

复制代码
 切入点定义,需要定义两个元素:
 1.切入点声明(private void myPointCut(){})
  - 在SpringAOP中切入点的声明其实就是方法定义,但无参数和方法体
  - 切入点的名称为方法名,在引用切入点时需要使用"方法名()"
 2.定义切入点表达式,由 @Pointcut注解定义
 @Pointcut:切入点表达式注解,通过切入点表达式对要拦截的方法描述
 execution:在其中编写切入点表达式
  - 切入点表达式是用于描述方法
java 复制代码
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Aspect //切面注解
@Component //当前类扔给Spring管理
@EnableAspectJAutoProxy //启用springAOP的自动代理功能
//切入点声明
public class MyAspect {
    //切入点表达式注解
    @Pointcut("execution(void com.jiazhong.service.impl.UserServiceImpl.add())")
    //切入点声明    
    private void myPointCut(){}
}

对于切入点表达式还有以下写法,并分别注释了其意思

java 复制代码
    //切入点定义拦截add方法
    @Pointcut("execution(void com.jiazhong.service.impl.UserServiceImpl.add())")

    //切入点定义拦截queryByName方法
    @Pointcut("execution(String com.jiazhong.service.impl.UserServiceImpl.queryByName(String))")

    //切入点定义拦截UserServiceImpl类中的所有方法,第一个*是所有类型,第二个*是类中所有方法,(..)是方法中的任意类型的任意参数
    @Pointcut("execution(* com.jiazhong.service.impl.UserServiceImpl.*(..))")

    //切入点定义拦截com.jiazhong.service包及其子包中的任意类任意方法
    @Pointcut("execution(* com.jiazhong.service..*.*(..))")

    //切入点定义不拦截指定的方法queryAll
    @Pointcut("!execution(void com.jiazhong.service.impl.UserServiceImpl.queryAll())")
复制代码
切面类,切面中包含两个元素:
  1.切入点,用于定义连接点的
  2.通知,拦截到连接点后要做的具体事情
   - 前置通知,在目标方法执行前执行
   - 后置通知,在目标方法执行后执行
   - 异常通知,在目标方法出现异常后执行
   - 最终通告,无论目标方法是否出现异常都会执行

①前置通知

java 复制代码
    /**
     * @Before("myPointCut()"):前置通知注解,myPointCut()指定切入点
     */
    @Before("myPointCut()")
    public void beforeAdvice(){
        System.out.println("前置通知被执行......");
    }

② 后置通知

java 复制代码
    /**
     * 后置通知,当目标方法调用后执行,但如果目标方法出现异常则不执行
     */
    @AfterReturning("myPointCut()")
    public void afterReturningAdvice(){
        System.out.println("后置通知被执行......");
    }

③异常通知

java 复制代码
    /**
     * 异常通知,在目标方法出现异常时执行
     */
    @AfterThrowing("myPointCut()")
    public void throwAdvice(){
        System.out.println("异常通知被执行......");
    }

④最终通知

java 复制代码
    /**
     * 最终通知,无论是否出现异常都被执行
     */
    @After("myPointCut()")
    public void afterAdvice(){
        System.out.println("最终通知被执行......");
    }

⑤环绕通知

复制代码
 环绕通知可以替换前面的所有通知
 原则:在环绕通知内部必须手动调用目标方法
 环绕通知带有参数ProceedingJoinPoint(处理连接点),使用该参数可以发起对目标方法的调用
java 复制代码
    /**
     * 环绕通知,可以在目标方法调用前、调用后、出现异常后自定义要执行的内容
     */
    @Around("myPointCut()")
    public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
        try {
            System.out.println("环绕通知:前置通知。。。。。");
            //调用目标方法
            //目标方法的返回值就是proceed方法的返回值
            String msg = (String) proceedingJoinPoint.proceed();
            System.out.println(msg);
            System.out.println("环绕通知:后置通知。。。。。");
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("环绕通知:异常通知。。。。。");
        }finally {
            System.out.println("环绕通知:最终通知。。。。。");
        }
    }

此处的实例是:

java 复制代码
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Aspect
@Component
@EnableAspectJAutoProxy
public class MyAspect {
    @Pointcut("execution(void com.jiazhong.service.impl.UserServiceImpl.add())")
    private void myPointCut(){}
    @Before("myPointCut()")
    public void beforeAdvice(){
        System.out.println("前置通知被执行......");
    }

5、UserTest测试类

java 复制代码
public class UserTest {
    @Test
    public void test(){
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = (UserService) context.getBean("userService");

        userService.add();
    }
}
复制代码
----SpringAOP注解
@Aspect:切面注解,在类上使用,表示该类为一个切面类
@EnableAspectJAutoProxy:启用SpringAOP的自动代理注解
@Pointcut:定义切入点表达式注解
@Before("切入点"):前置通知注解
@AfterReturning("切入点"):后置通知注解
@AfterThrowing("切入点"):异常通知注解
@After("切入点"):最终通知注解
@Around("切入点"):环绕通知注解
相关推荐
linux kernel14 分钟前
第六部分:数据链路层
服务器·网络
侠客行03176 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪6 小时前
深入浅出LangChain4J
java·langchain·llm
子兮曰6 小时前
OpenClaw入门:从零开始搭建你的私有化AI助手
前端·架构·github
吴仰晖6 小时前
使用github copliot chat的源码学习之Chromium Compositor
前端
1024小神6 小时前
github发布pages的几种状态记录
前端
较劲男子汉7 小时前
CANN Runtime零拷贝传输技术源码实战 彻底打通Host与Device的数据传输壁垒
运维·服务器·数据库·cann
老毛肚7 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
wypywyp8 小时前
8. ubuntu 虚拟机 linux 服务器 TCP/IP 概念辨析
linux·服务器·ubuntu
风流倜傥唐伯虎8 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot