(35)使用Spring的AOP

Spring对AOP的实现包括以下3种方式:

  • 第一种方式:Spring框架结合AspectJ框架实现的AOP,基于注解方式。
  • 第二种方式:Spring框架结合AspectJ框架实现的AOP,基于XML方式。
  • 第三种方式:Spring框架自己实现的AOP,基于XML配置方式。

实际开发中,都是Spring+AspectJ来实现AOP。所以我们重点学习第一种和第二种方式。

什么是AspectJ?(Eclipse组织的一个支持AOP的框架。AspectJ框架是独立于Spring框架之外的一个框架,Spring框架用了AspectJ)

AspectJ项目起源于帕洛阿尔托(Palo Alto)研究中心(缩写为PARC)。该中心由Xerox集团资助,Gregor Kiczales领导,从1997年开始致力于AspectJ的开发,1998年第一次发布给外部用户,2001年发布1.0 release。为了推动AspectJ技术和社团的发展,PARC在2003年3月正式将AspectJ项目移交给了Eclipse组织,因为AspectJ的发展和受关注程度大大超出了PARC的预期,他们已经无力继续维持它的发展。

15.4.1 准备工作

使用Spring+AspectJ的AOP需要引入的依赖如下:

xml 复制代码
<!--spring context依赖-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>6.0.0-M2</version>
</dependency>
<!--spring aop依赖-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>6.0.0-M2</version>
</dependency>
<!--spring aspects依赖-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>6.0.0-M2</version>
</dependency>

Spring配置文件中添加context命名空间和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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>

15.4.2 基于AspectJ的AOP注解式开发

实现步骤

第一步:定义目标类以及目标方法

java 复制代码
package com.powernode.spring6.service;

// 目标类
public class OrderService {
    // 目标方法
    public void generate(){
        System.out.println("订单已生成!");
    }
}

第二步:定义切面类

java 复制代码
package com.powernode.spring6.service;

import org.aspectj.lang.annotation.Aspect;

// 切面类
@Aspect
public class MyAspect {
}

第三步:目标类和切面类都纳入spring bean管理

在目标类OrderService上添加**@Component注解。
在切面类MyAspect类上添加
@Component**注解。

第四步:在spring配置文件中添加组建扫描

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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--开启组件扫描-->
    <context:component-scan base-package="com.powernode.spring6.service"/>
</beans>

第五步:在切面类中添加通知

java 复制代码
package com.powernode.spring6.service;

import org.springframework.stereotype.Component;
import org.aspectj.lang.annotation.Aspect;

// 切面类
@Aspect
@Component
public class MyAspect {
    // 这就是需要增强的代码(通知)
    public void advice(){
        System.out.println("我是一个通知");
    }
}

第六步:在通知上添加切点表达式

java 复制代码
package com.powernode.spring6.service;

import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.aspectj.lang.annotation.Aspect;

// 切面类
@Aspect
@Component
public class MyAspect {
    
    // 切点表达式
    @Before("execution(* com.powernode.spring6.service.OrderService.*(..))")
    // 这就是需要增强的代码(通知)
    public void advice(){
        System.out.println("我是一个通知");
    }
}

注解@Before表示前置通知。

第七步:在spring配置文件中启用自动代理

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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--开启组件扫描-->
    <context:component-scan base-package="com.powernode.spring6.service"/>
    <!--开启自动代理-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

<aop:aspectj-autoproxy proxy-target-class="true"/> 开启自动代理之后,凡事被代理的 目标类(Target Class),即那些被切点表达式匹配到的、需要增强的 Bean 都会生成代理对象。

proxy-target-class="true" 表示采用cglib动态代理。

proxy-target-class="false" 表示采用jdk动态代理。默认值是false。即使写成false,当没有接口的时候,也会自动选择cglib生成代理类。

测试程序:

java 复制代码
package com.powernode.spring6.test;

import com.powernode.spring6.service.OrderService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AOPTest {
    @Test
    public void testAOP(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aspectj-aop-annotation.xml");
        OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
        orderService.generate();
    }
}
相关推荐
Fuyo_111924 分钟前
C++ AVL树保姆级详解:从平衡因子到四大旋转机制
java·c++·算法
dishugj25 分钟前
oracle日志切换三条命令区别
数据库
Patrick在香港38 分钟前
一个斜杠,把毫秒变成十几秒
android·数据库·python·性能优化·正则表达式·回溯·redos
Sarvartha42 分钟前
Date、LocalDate、LocalTime、LocalDateTime、DateTimeFormatter类
java
悟道书生44 分钟前
(一)Navicate为什么转存结构和数据只转存表而不包含建库?
数据库·oracle
阿俊-全栈开发1 小时前
LikeShop 多商户 Java 版商城微服务模块拆分与部署架构演进实践
java·微服务·架构·likeshop开源商城·多商户源码
赤龙ERP1 小时前
ERP周报:连接器开闸、国产GPU进场与智能工厂253家
数据库·人工智能·大模型·rpa·erp·企业数字化·builderpattern
Wang's Blog1 小时前
Java 项目实战:交友项目 - 联系人列表
java·开发语言·交友
lusklusklusk1 小时前
SQL Server补丁版本号为什么“日期新反而版本低”?——GDR、CU、CU+GDR 版本号规则与升级路径详解
数据库
我命由我123451 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理