Java后置通知(After Advice)实现案例
后置通知(After Advice)是在目标方法执行后执行的增强,无论方法是否抛出异常都会执行,下面是几个实现案例:

基于Spring AOP的XML配置实现
1 定义目标接口和实现类
// 目标接口
public interface UserService {
void addUser(String username);
void deleteUser(int userId) throws Exception;
}
// 目标实现类
public class UserServiceImpl implements UserService {
@Override
public void addUser(String username) {
System.out.println("添加用户:" + username);
}
@Override
public void deleteUser(int userId) throws Exception {
System.out.println("删除用户,ID:" + userId);
if (userId <= 0) {
throw new Exception("用户ID无效");
}
}
}
2 定义后置通知切面类
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class LogAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
System.out.println("===== 后置通知开始 =====");
System.out.println("目标类:" + target.getClass().getName());
System.out.println("方法名:" + method.getName());
System.out.println("参数:");
if (args != null) {
for (Object arg : args) {
System.out.println(" - " + arg);
}
}
System.out.println("返回值:" + returnValue);
System.out.println("===== 后置通知结束 =====");
}
}
3 Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 目标对象 -->
<bean id="userServiceTarget" class="com.example.UserServiceImpl"/>
<!-- 后置通知 -->
<bean id="logAfterAdvice" class="com.example.LogAfterAdvice"/>
<!-- 创建代理 -->
<bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="userServiceTarget"/>
<property name="interceptorNames">
<list>
<value>logAfterAdvice</value>
</list>
</property>
</bean>
</beans>
基于@AspectJ注解实现
1 切面类(使用@After注解)
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
// 后置通知 - 在方法执行后执行,无论是否抛出异常
@After("execution(* com.example.UserService.*(..))")
public void afterMethod(JoinPoint joinPoint) {
System.out.println("===== @After后置通知 =====");
System.out.println("目标方法:" + joinPoint.getSignature().getName());
System.out.println("目标类:" + joinPoint.getTarget().getClass().getSimpleName());
System.out.println("参数:" + Arrays.toString(joinPoint.getArgs()));
System.out.println("==========================");
}
// 返回通知 - 只在方法正常返回时执行
@AfterReturning(pointcut = "execution(* com.example.UserService.*(..))",
returning = "result")
public void afterReturningMethod(JoinPoint joinPoint, Object result) {
System.out.println("===== @AfterReturning返回通知 =====");
System.out.println("方法正常返回,返回值:" + result);
System.out.println("================================");
}
// 异常通知 - 只在方法抛出异常时执行
@AfterThrowing(pointcut = "execution(* com.example.UserService.*(..))",
throwing = "exception")
public void afterThrowingMethod(JoinPoint joinPoint, Exception exception) {
System.out.println("===== @AfterThrowing异常通知 =====");
System.out.println("方法抛出异常:" + exception.getMessage());
System.out.println("================================");
}
}
2 Spring配置(启用AspectJ)
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.example")
public class AppConfig {
// 其他bean配置
}
测试代码
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AfterAdviceTest {
public static void main(String[] args) {
// XML配置方式
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
// 测试正常执行
System.out.println("=== 测试正常执行 ===");
userService.addUser("张三");
System.out.println("\n=== 测试抛出异常 ===");
try {
userService.deleteUser(-1);
} catch (Exception e) {
System.out.println("捕获到异常:" + e.getMessage());
}
}
}
使用AspectJ LTW(加载时织入)
// 配置META-INF/aop.xml
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<aspects>
<aspect name="com.example.LoggingAspect"/>
</aspects>
<weaver>
<include within="com.example..*"/>
</weaver>
</aspectj>
实际应用场景示例
@Aspect
@Component
public class TransactionManagementAspect {
// 后置通知:关闭数据库连接
@After("execution(* com.example.dao.*.save*(..))")
public void closeConnection(JoinPoint joinPoint) {
System.out.println("关闭数据库连接");
// 实际应用中释放连接资源
}
// 后置通知:记录操作日志
@After("execution(* com.example.service.*.*(..)) && !execution(* com.example.service.*.get*(..))")
public void logOperation(JoinPoint joinPoint) {
String method = joinPoint.getSignature().getName();
String user = SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println(String.format("用户[%s]执行了操作[%s]", user, method));
}
// 后置通知:清理缓存
@After("execution(* com.example.service.*.update*(..))")
public void clearCache(JoinPoint joinPoint) {
String entityName = joinPoint.getTarget().getClass().getSimpleName();
CacheManager.clearCache(entityName);
System.out.println("清理了" + entityName + "的缓存");
}
}
关键要点
- @After:无论方法正常结束还是抛出异常都执行
- @AfterReturning:只在方法正常返回时执行
- @AfterThrowing:只在方法抛出异常时执行
- JoinPoint:可以获取目标方法的信息
这种实现方式广泛应用于日志记录、事务管理、权限检查、性能监控等场景。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播