一、maven导入依赖
主要为 ioc容器 test 切入点表达式解析器 aop
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<groupId>org.example</groupId>
<artifactId>spring-aop-2</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!-- Spring Ioc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- 解析切入点表达式 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!-- 配置juint4 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 配置 Spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
二、测试类
业务层接口
package com.service;
/**
* @author gxm
* @date 2020/5/6 10:18
* @description This is description of class
* @since version-1.0
*/
public interface IAccountService {
/**
* 模拟保存账户
* @author gxm
* @date 2020/5/6 10:18
* @description This is description of method
* @param 1
* @return void
* @since version-1.0
*/
void saveAccount();
/**
* 模拟更新账户
* @author gxm
* @date 2020/5/6 10:19
* @description This is description of method
* @param i 1
* @return void
* @since version-1.0
*/
void updateAccount(int i);
/**
* 模拟删除账户
* @author gxm
* @date 2020/5/6 10:19
* @description This is description of method
* @param
* @return void
* @since version-1.0
*/
int deleteAccount();
}
业务层具体实现:
package com.service.impl;
import com.service.IAccountService;
/**
* Created with IntelliJ IDEA.
*
* @author : gxm
* @date : 2020/5/6
* @time : 10:20
* @projectName : spring-aop-2
* @description :
* To change this template use File | Settings | File Templates.
* Description:
**/
public class AccountServiceImpl implements IAccountService {
@Override
public void saveAccount() {
System.out.println("保存");
}
@Override
public void updateAccount(int i) {
System.out.println("更新 "+i);
}
@Override
public int deleteAccount() {
System.out.println("删除");
return 0;
}
}
切入点的通知类及方法:
package com.util;
/**
* Created with IntelliJ IDEA.
*
* @author : gxm
* @date : 2020/5/6
* @time : 10:22
* @projectName : spring-aop-2
* @description :
* To change this template use File | Settings | File Templates.
* Description:
**/
public class Logger {
/**
* 打印日志 在切入点前执行
*
* @param
* @return void
* @author gxm
* @date 2020/5/6 10:23
* @description This is description of method
* @since version-1.0
*/
public void print() {
System.out.println("记录日志");
}
}
三、bean的xml配置及切入点表达式语言
主要关注点如下:
- 业务层需要增强的bean,下述为
com.service.impl.AccountServiceImpl
- 切入点的通知类bean即增强的具体实现部分
com.util.Logger
- 利用
aop:config
配置一个AOP -
aop:aspect
配置一个切面 - 根据需要配置一个或多个通知,前置 后置 环绕 异常 最终,下文示例配置一个前置方法
aop:before
- 配置前置方法及切入点,切入点表达式规则如下,需要提供切入点表达式解析jar,即maven中的
aspectjweaver
配置步骤如下:
1. 把通知bean交给Spring
2. aop:config 标签表明开始AOP的配置
3. 使用apo:aspect表明标签配置切面
id 给切面提供一个唯一标志
ref 指定通知类bean的id
4. aop:aspect标签的内部使用,对应标签来配置通知的类型
示例 切入点之前执行日志打印,故为前置通知,aop:before 表示前置通知
method 指定切入点的前置执行的方法
pointcut 切入点表达式,表示对业务层的哪些方法增强。
切入点表达式写法:
关键字:execute(表达式)
表达式:访问修饰符 返回值 包名.包名....类名.方法名.方法名(参数列表)
标准写法: saveAccount
public void com.service.impl.AccountServiceImpl.saveAccount()
访问修饰符可以省略
void com.service.impl.AccountServiceImpl.saveAccount()
返回值可以使用通配符表示任意返回值
* com.service.impl.AccountServiceImpl.saveAccount()
包名可以使用通配符表示任意包,但需要*数量等于包名级数
* *.*.*.AccountServiceImpl.saveAccount()
包名可以使用 .. 替代当前包及其子包
* *.*..AccountServiceImpl.saveAccount()
类名和方法名都可以使用*来通配
* *.*..*.saveAccount()//匹配所有的*.*包及其子包的有saveAccount()方法
* *.*..*.*() //匹配所有*.*包及其子包的所有无参方法
参数列表:
可以直接下参数类型:
基本类型直接写
引用类型:全路径 例如 java.lang.String
类型可以使用通配符表示任意类型:
但参数的个数必须与*个数相等
可以使用..表示有无参数均可,有参数则为任意类型
* *.*..*.*(..) //开发中不建议使用,会对所有方法增强
全通配写法:
* *..*.*(..)
实际开发中使用:
切到业务层实现类下的所有方法:
* *.*.*.AccountServiceImpl.*(..)
<?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">
<!-- 配置IoC 将service对象加入容器 -->
<bean id="accountService" class="com.service.impl.AccountServiceImpl"/>
<!-- 通知类logger -->
<bean id="logger" class="com.util.Logger"/>
<!-- 配置AOP -->
<aop:config>
<!-- 配置切面 -->
<aop:aspect id="logAdvice" ref="logger">
<!-- 配置通知类型 通知的方法 切入点 -->
<aop:before method="print" pointcut="execution( * *.*.*.AccountServiceImpl.*(..))"/>
</aop:aspect>
</aop:config>
</beans>