阅读本篇前至少应该已经熟知Spring AOP中的切面、切入点、通知三者的概念和具体应用含义(详见:《Spring框架汇总(Spring AOP——理论基础)》),并且最好已经能够通过XML配置文件来使用Spring AOP编程(详见:《Spring框架汇总(Spring AOP——基于XML的简单案例)》与《Spring框架汇总(Spring AOP——基于XML的进阶案例)》)。
创建Maven项目,引入相关的依赖后便可以开始测试。
编写核心业务接口和实现类:
package com.test.service;
/**
* 核心业务接口
* @author Elio
*/
public interface UserService {
void saveUser(String user);
int updateUser(String user);
Object findUserById(Integer id);
}
package com.test.service.impl;
import org.springframework.stereotype.Service;
import com.test.service.UserService;
/**
* 核心业务实现类
* @author Elio
*/
@Service
public class UserServiceImpl implements UserService {
public void saveUser(String user) {
System.out.println("save "+user);
throw new RuntimeException("save.exception");
}
public int updateUser(String user) {
System.out.println("update "+user);
return 1;
}
public Object findUserById(Integer id) {
System.out.println("findUserById "+id);
return 200;
}
}
编写切面类:
package com.test.aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 定义切面
* @author Elio
*/
//将该类交由Spring管理
@Component
//告知Spring这是一个切面
@Aspect
public class TxManagerAspect {
/**
* 前置通知,在目标方法执行前执行
*/
@Before("within(com.test.service.impl.*)")
public void beforeAdvice(){
System.out.println("tx.beforeAdvice");
}
/**
* 返回通知,假如核心业务执行结束,没有出现异常则会执行该通知
*/
@AfterReturning("within(com.test.service.impl.UserServiceImpl)")
public void returnAdvice(){
System.out.println("returnAdvice");
}
/**
* 异常通知,当核心业务方法出现异常时会执行此通知
*/
@AfterThrowing("bean(userServiceImpl)")
public void afterThrowing(){
System.out.println("afterThrowing");
}
/**
* 后置通知,无论核心业务是否正常结束,这个通知都会执行,通常将此通知理解为最终通知
*/
@After("within(com.test.service..*)")
public void afterAdvice(){
System.out.println("afterAdvice");
}
//使用try-catch-finally块来帮助理解,但实际上并不能完全等同于此,只是帮助理解
/**
* try{
* @Before
* 核心业务
* @AfterReturn
* }catch(Exception e){
* throw e;
* @AfterThrowing
* }finally{
* @After
* }
*/
}
输出结果:
beforeAdvice
update Jerry
afterAdvice
returnAdvice
再来看有异常抛出的情况。
核心业务实现类UserServiceImpl的saveUser方法会抛出一个运行时异常:
public void saveUser(String user) {
System.out.println("save "+user);
throw new RuntimeException("save.exception");
}
将单元测试类中的测试方法改为执行saveUser():
@Test
public void testUserUpdate(){
UserService userService=ctx.getBean("userServiceImpl",UserService.class);
userService.saveUser("Jerry");
}
输出结果:
beforeAdvice
save Jerry
afterAdvice
afterThrowing
如此便完成了一个简单的完全基于注解的Spring AOP应用案例,进阶案例见于《Spring框架汇总(Spring AOP——基于注解的进阶案例)》。