AOP功能代码实例---Spring源码从入门到精通(十七)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: AOP功能代码实例---Spring源码从入门到精通(十七)

上篇文章主要介绍了@Profile注解:

可以对不同的开发环境(test,dev),选择性加载不同的组件,如果用AnnocationConfigApplicationContext,需要用无参构造函数,先自己getEnviroment,设置指定加载的test环境,还是dev环境。


IOC目录总结---Spring源码从入门到精通(十六)

Spring源码从入门到精通---@Profile(十五)



这篇文章主要介绍面向切面AOP:

动态代理,面向切面aop是一种开发思想,指在系统运行的情况下,吧代码插入到项目中指定的位子。


一、定义业务逻辑 类 和 切面类


首先必须把这两个类交给ioc容器管理,业务逻辑运行之后,切面类监听到业务逻辑正在运行,切面类可以用@pointCut指定监听的目标类,用切入点表达式,用@Aspect注解表示当前类是一个切面类。


导入aop切面maven包:

<!--Aop-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.3.12.RELEASE</version>
    </dependency>

业务逻辑类:

/**
 * @author keying
 */
public class MathCalculator {
    public int div(Integer i, Integer z) {
        //我们可以吧日志写在这里,但这是一种耦合的方式,并不符合aop编程思想
        //System.out.println("打印日志!");
        System.out.println("div正在计算。。。");
        return i / z;
    }
}

日志监听类:


从下面代码可以看到,用了

1、@Apect告诉spring这是一个切面类。

2、分别写了四个方法,开始start(注解 @Before),结束end(注解@After),returnSuccess返回成功(注解@AfterReturning),returnException业务异常(注解@AfterThrowing)。可以在每个方法上单独标注切入的目标。下面代码用@PointCut注解指定了一个公用的方法。

3、JoinPoint可以获取到切面目标的方法名 和 参数名等信息。

/**
 * @author keying
 * @Aspect:告诉springIOC,这是一个切面类
 */
@Aspect
public class LogAspects {
    /**
     * 抽取公共切入点表达式
     */
    @Pointcut("execution(public int com.alibaba.aop.MathCalculator.*(..))")
    public void pointCut() {
    }
    //业务方法之前切入
    //@Before("public int com.alibaba.aop.MathCalculator.div(Integer,Integer)")
    //@Before("public int com.alibaba.aop.MathCalculator.*(..)")
    @Before("pointCut()")
    public void start(JoinPoint joinPoint) {
        //获取切面目标方法名 和 参数列表
        Object[] objects = joinPoint.getArgs();
        System.out.println(joinPoint.getSignature().getName() + "计算开始 ---{" + Arrays.asList(objects) + "}");
    }
    //@After("public int com.alibaba.aop.MathCalculator.*(..)")
    @After("com.alibaba.aop.LogAspects.pointCut()")
    public void end() {
        System.out.println("计算结束 ---{}");
    }
    /**
     * 定义aop返回成功,用object接收返回成功参数
     * 重点,重点,重点:joinPoint必须写在参数第一位,否则spring无法解析
     */
    @AfterReturning(value = "pointCut()", returning = "object")
    public void returnSuccess(JoinPoint joinPoint, Object object) {
        System.out.println(joinPoint.getSignature().getName() + "计算返回成功 ---{" + object + "}");
    }
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void returnException(Exception exception) {
        System.out.println("计算异常 ---{" + exception + "}");
    }
}

aop配置类:

下面用@Bean和@Import方法吧业务逻辑类 和 切面类交给springioc容器管理。@EnableAspectAutoProxy开启aop模式代理。

/**
 * AOP:动态代理。(编程思想)
 * 在程序运行时候,动态的将某段代码插入项目中指定位子的编程方式。
 *
 * 测试思想:
 * 定义一个业务逻辑类,在程序运行的时候,将他的日志打印(运行之前,运行之后,运行正常返回,计算异常等等)。
 * 定义一个日志切面类,动态的感知业务逻辑运行到哪里。
 * 通知方法:
 * 1)、前置通知(@Before):start,目标业务运行之前运行
 * 2)、后置通知(@After):end,目标业务运行结束之后运行。(无论正常结束还是异常结束)
 * 3)、返回通知(@AfterReturning):returnSuccess,目标业务运行成功
 * 4)、异常通知(@AfterThrowing):returnException,目标业务运行异常
 * 5)、环绕通知(@Around):动态代理,手动推进目标业务运行,joinPoint。
 *
 * @EnableAspectAutoProxy开启基于注解的aop模式代理
 *
 * @author keying
 */
@EnableAspectJAutoProxy
@Configuration
@Import({LogAspects.class})
public class MyConfigAop {
    @Bean(value = "mathCalculator")
    public MathCalculator mathCalculator(){
        return new MathCalculator();
    }
  /*  @Bean(value = "logAspects")
    public LogAspects logAspects(){
        return new LogAspects();
    }*/
}

junitTest:加载类改为aop配置类,从ioc容器中获取对象测试,不要自己创建对象测试,否则aop切面不生效。

/**
 * @author keying
 *
 * 自己实现AOP主要分为三步:
 * 1、自定义业务逻辑类 和 aop切面类,aop类加上@Aspect切面注解。
 * 2、给aop切面类每个方法加上注解,告知何时运行,切入点表达式@PointCut
 * 3、在配置类注解开启aop模式:@EnableAsceptAutoProxy
 */
public class AOPTestPointCut {
    @Test
    public void test() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
            MyConfigAop.class);
        //这种自己创建的对象不会触发aop切面,需要从ioc容器中获取
      /*  MathCalculator mathCalculator = new MathCalculator();
        System.out.println(mathCalculator.div(1, 2));*/
        MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
        System.out.println("IOC容器获取后计算:" + mathCalculator.div(1, 2));
        applicationContext.close();
    }
}

运行之后可以看到,切面日志 在div运行之前有运行,在计算结束之后会返回成功,并且目标类的方法名称 、 参数 、返回值 都可以获取到。

image.png

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
179 6
|
1月前
|
安全 API
鸿蒙开发:实现AOP代码插桩能力
正确的运用AOP,可以提升代码的模块化、复用性、可维护性和灵活性,同时降低了耦合度,使系统更易于扩展和维护。
66 13
鸿蒙开发:实现AOP代码插桩能力
|
30天前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot中使用拦截器——拦截器使用实例
本文主要讲解了Spring Boot中拦截器的使用实例,包括判断用户是否登录和取消特定拦截操作两大场景。通过token验证实现登录状态检查,未登录则拦截请求;定义自定义注解@UnInterception实现灵活取消拦截功能。最后总结了拦截器的创建、配置及对静态资源的影响,并提供两种配置方式供选择,帮助读者掌握拦截器的实际应用。
33 0
|
30天前
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
60 0
|
30天前
|
Java 开发者 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——什么是AOP
本文介绍了Spring Boot中的切面AOP处理。AOP(Aspect Oriented Programming)即面向切面编程,其核心思想是分离关注点。通过AOP,程序可以将与业务逻辑无关的代码(如日志记录、事务管理等)从主要逻辑中抽离,交由专门的“仆人”处理,从而让开发者专注于核心任务。这种机制实现了模块间的灵活组合,使程序结构更加可配置、可扩展。文中以生活化比喻生动阐释了AOP的工作原理及其优势。
42 0
|
2月前
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
163 25
|
2月前
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
107 24
|
3月前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
161 8
|
30天前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
52 0
|
30天前
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
62 0