Spring AOP:面向切面编程的最佳实践 ( 二 )

3.SpringAOP应用实例

3.1.导入依赖

通过 spring-context 会依赖导入 spring核心包, 而spring-aspects 用于提供AspectJ的支持

xml 复制代码
    <!-- Spring AOP 相关依赖 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.3.6</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.6</version>
    </dependency>

    <!-- 如果需要使用代理功能 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.3.6</version>
    </dependency>

如果 用于AspectJ的运行时和编译时/加载时编织的功能 还要导入aspectjrtaspectjweaver

xml 复制代码
    <!-- 如果使用 AspectJ 编译时或加载时织入 -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.9.7</version>
    </dependency>
	<dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version>
    </dependency>

3.2.实现代码

3.2.1.业务类

增加 @Component 注册到Spring IoC容器中

java 复制代码
import org.springframework.stereotype.Component;

@Component
public class GymAop {

    // 业务 A : 举重训练
    public String  weightLifting() {
        System.out.println( "进行举重训练。" );
        return "感觉不断在进步!";
    }

    // 业务 B : 瑜伽课
    public void yogaClass(String type) {
        System.out.println( "参加 " + type + " [ 瑜伽课 ]。");
    }

    // 业务 C : 游泳训练
    public void swimming() {
        System.out.println( "在游泳池里游泳。");
    }

}
3.2.2.切面类
java 复制代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.swing.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

@Aspect
@Component
public class AspectAop {

    //前置的方法
    // 功能 A : 推荐老师
    @Before("execution(* com.yuan.aop.GymAop.*(..))")
    public void selectMaster(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        String type = "";
        if (args != null && args.length > 0) {
            type = "根据您的要求: " + Arrays.toString( args );
        }
        System.out.println( "首先 : " + type + " 我们为您推荐一位指导老师!" );
    }

    //后置的方法
    //功能 B : 结束提示
    @After("execution(* com.yuan.aop.GymAop.*(..))")
    public void  overTip(JoinPoint joinPoint ){
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        System.out.println( "您在 " + new Date() + " 结束了" + method.getName() );
    }

    //环绕的方法
    @Around("execution(* com.yuan.aop.GymAop.*(..))")
    public Object doBasicProfiling(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object[] args = proceedingJoinPoint.getArgs();
        // 修改 传入的参数
        if (args != null && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                args[i] = " { " + args[i] + " } ";
            }
        }
        //执行方法
        Object obj = proceedingJoinPoint.proceed(args);

        // 修改 返回值
        if (obj!=null) {
            obj = " { " + obj + " } ";
        }

        // 方法返回值
        return obj;
    }
}
3.2.3.测试类
java 复制代码
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class TestAop {
    public static void main(String[] args)
    {
        AnnotationConfigApplicationContext spring = new AnnotationConfigApplicationContext(TestAop.class);
        GymAop bean = spring.getBean(GymAop.class);

        bean.yogaClass("综合");
        System.out.println("-----");

        String feel = bean.weightLifting();
        System.out.println("您的评价是:" + feel );

        System.out.println("-----");
        bean.swimming();
    }
}
3.2.4.运行测试
text 复制代码
首先 : 根据您的要求: [ { 综合 } ] 我们为您推荐一位指导老师!
参加  { 综合 }  [ 瑜伽课 ]。
您在 Fri Aug 02 21:52:23 CST 2024 结束了yogaClass
-----
首先 :  我们为您推荐一位指导老师!
进行举重训练。
您在 Fri Aug 02 21:52:23 CST 2024 结束了weightLifting
您的评价是: { 感觉不断在进步! } 
-----
首先 :  我们为您推荐一位指导老师!
在游泳池里游泳。
您在 Fri Aug 02 21:52:23 CST 2024 结束了swimming

3.3.xml配置方式

通过 xml 进行配置aop 的方式, 现在通常使用 注解式

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
    
	<!-- 定义目标 -->
	<bean id="gymAop" class="com.yuan.aop.GymAop"></bean> 
    
   	<!-- 定义切面 -->
    <bean id="aspectAop" class="com.yuan.aop.AspectAop"></bean> 
     
    <aop:config> 
     <aop:aspect id="myaop" ref="aspectAop"> 
     
         <aop:pointcut id="mycut" expression="execution(* com.yuan.aop.*.*(..))"/> 
     
	     <aop:before  pointcut-ref="mycut" method="selectMaster" /> 
	     <aop:after   pointcut-ref="mycut" method="overTip"/> 
	     <aop:around  pointcut-ref="mycut" method="doBasicProfiling"/> 
     </aop:aspect> 
   </aop:config> 
    
    <!-- 开启AOP自动代理 -->
    <aop:aspectj-autoproxy />
    
</beans>

3.4.SpringBoot中使用AOP

使用SpringBoot,许多相关依赖已经包含在了Spring Boot的starter依赖中

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

并且 使用 @SpringBootApplication 代替了 @Configuration, @ComponentScan, @EnableAspectJAutoProxy

相关推荐
夏天的味道٥3 小时前
使用 Java 执行 SQL 语句和存储过程
java·开发语言·sql
冰糖码奇朵5 小时前
大数据表高效导入导出解决方案,mysql数据库LOAD DATA命令和INTO OUTFILE命令详解
java·数据库·sql·mysql
好教员好5 小时前
【Spring】整合【SpringMVC】
java·spring
浪九天6 小时前
Java直通车系列13【Spring MVC】(Spring MVC常用注解)
java·后端·spring
小斌的Debug日记6 小时前
框架基本知识总结 Day16
redis·spring
堕落年代7 小时前
Maven匹配机制和仓库库设置
java·maven
m0_748246877 小时前
maven导入spring框架
数据库·spring·maven
功德+n7 小时前
Maven 使用指南:基础 + 进阶 + 高级用法
java·开发语言·maven
香精煎鱼香翅捞饭7 小时前
java通用自研接口限流组件
java·开发语言
ChinaRainbowSea8 小时前
Linux: Centos7 Cannot find a valid baseurl for repo: base/7/x86_64 解决方案
java·linux·运维·服务器·docker·架构