项目需求
-
通过日志记录每次accountService业务的执行状况
-
为切入点配置前置通知,异常通知,后置通知,最终通知,环绕通知
项目说明
- 项目使用基于注解的方式配置aop
- 项目不涉及数据库操作,不涉及事务控制,只是简单的关于aop的使用
- 不涉及真正的日志管理,只是简单模拟日记记录的运行方式
- 项目简单演示了前置通知,异常通知,后置通知,最终通知和环绕通知
- 基于注解配置aop会出现几个通知顺序出现异常,环绕通知没有这个问题
编写pom文件
使用aop时需要导入AspectJ坐标
<?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>
<groupId>com.cncs</groupId>
<artifactId>day03_05aop_anno</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
</project>
新建模拟日志记录类Logger
-
添加
@Component
将其声明为一个bean -
添加
@Aspect
注解将其声明为一个切面类 -
配置切入点表达式,定义我们要拦截的方法
-
为各类通知方法添加各个通知注解,声明通知的类型
package com.cncs.utils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 日志记录类
*/
@Component("logger")
@Aspect
public class Logger {
@Pointcut("execution(* com.cncs.service.impl.*.*(..))")
public void pt1(){}
/**
* 前置通知
*/
// @Before("pt1()")
public void beforePrintLog() {
System.out.println("前置....");
}
/**
* 异常通知
*/
// @AfterThrowing("pt1()")
public void afterThrowingPrintLog() {
System.out.println("异常....");
}
/**
* 后置通知
*/
// @AfterReturning("pt1()")
public void afterReturningPrintLog() {
System.out.println("后置....");
}
/**
* 最终通知
*/
// @After("pt1()")
public void afterPrintLog() {
System.out.println("最终....");
}
@Around("pt1()")
public Object aroundPrintLog(ProceedingJoinPoint pjp){
//设置返回值
Object returnVal = null;
//获取参数
Object[] args = pjp.getArgs();
try{
System.out.println("环绕通知....前置");
returnVal = pjp.proceed(args);
System.out.println("环绕通知....后置");
return returnVal;
}catch (Exception e){
System.out.println("环绕通知....异常");
throw new RuntimeException();
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
System.out.println("环绕通知....最终");
}
return null;
}
}
新建账户的接口AccountService
package com.cncs.service;
public interface AccountService {
void save();
}
新建账户接口的实现类AccountServiceImpl
package com.cncs.service.impl;
import com.cncs.service.AccountService;
import org.springframework.stereotype.Service;
@Service("accountService")
public class AccountServiceImpl implements AccountService {
@Override
public void save() {
System.out.println("保存成功");
}
}
新建spring核心配置文件bean.xml,并开启对注解aop的支持
<?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"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 告知spring容器要扫描的包-->
<context:component-scan base-package="com.cncs"></context:component-scan>
<!-- 开启aop的注解支持-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
新建测试类AccountTest
package com.cncs.test;
import com.cncs.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:bean.xml")
public class AccountTest {
@Autowired
private AccountService accountService;
@Test
public void testAopAdvice(){
accountService.save();
}
}