8.Spring AOP 实践案例
8.1.事务管理
- 问题场景:当应用程序执行多个数据库操作时,如果其中任何一个操作失败,就需要回滚所有已执行的操作。事务管理确保了数据的一致性和完整性。
- 解决方案:使用 Spring AOP 可以在方法调用前后自动开启和提交事务,或者在发生异常时回滚事务。
事务管理配置 (TransactionConfig.java)
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
切面类 (TransactionAspect.java)
@Aspect
@Component
public class TransactionAspect {
@Autowired
private PlatformTransactionManager transactionManager;
@Around("execution(* com.example.service.*.*(..))")
public Object handleTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
Object result = joinPoint.proceed();
transactionManager.commit(status);
return result;
} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
}
}
8.2.日志记录
- 问题场景:记录关键方法的调用时间和参数信息有助于追踪问题和调试。
- 解决方案:使用 Spring AOP 可以方便地记录方法的调用细节。
日志记录切面 (LoggingAspect.java)
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("LoggingAspect: Before " + joinPoint.getSignature().getName());
}
@AfterReturning(value = "execution(* com.example.service.*.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("LoggingAspect: After " + joinPoint.getSignature().getName() + ", Result: " + result);
}
}
8.3.安全认证
- 问题场景:在访问敏感资源前,通常需要验证用户的身份和权限。
- 解决方案:使用 Spring AOP 可以在方法调用前执行权限检查。
安全认证切面 (SecurityAspect.java)
@Aspect
@Component
public class SecurityAspect {
@Before("execution(* com.example.service.*.*(..))")
public void checkPermissions(JoinPoint joinPoint) {
// 假设有一个方法可以检查权限
boolean hasPermission = checkUserHasPermission(joinPoint.getSignature().getName());
if (!hasPermission) {
throw new SecurityException("Access denied.");
}
}
private boolean checkUserHasPermission(String methodName) {
// 模拟权限检查逻辑
return true; // 假设所有用户都有权限
}
}
8.4.性能监控
- 问题场景:监控方法的执行时间可以帮助优化性能瓶颈。
- 解决方案:使用 Spring AOP 可以在方法调用前后记录时间差,并输出性能数据。
性能监控切面 (PerformanceMonitoringAspect.java)
@Aspect
@Component
public class PerformanceMonitoringAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long elapsedTime = System.currentTimeMillis() - start;
System.out.println("PerformanceMonitoringAspect: " + joinPoint.getSignature().getName() + " took " + elapsedTime + " ms");
return result;
}
}
以上就是使用 Spring AOP 进行配置和实践的一些例子。这些示例展示了如何将 AOP 应用于实际的应用场景中,从而简化开发工作并提高代码的可维护性。
9.Spring AOP 的高级主题
9.1.引入 (Introduction)
-
定义:引入是 Spring AOP 中的一种特殊的通知类型,它允许向现有类添加新的接口和方法。引入通常用于为现有类添加新的行为,而不改变原有的实现。
-
示例:展示如何使用引入为现有类添加新的行为。
引入接口 (MyInterface.java)
public interface MyInterface {
void customMethod();
}
引入切面 (IntroductionAspect.java)
@Aspect
@Component
public class IntroductionAspect {
@DeclareParents(value = "com.example.service.*", defaultImpl = MyInterfaceImpl.class)
public static MyInterface myInterface;
@Component
public static class MyInterfaceImpl implements MyInterface {
@Override
public void customMethod() {
System.out.println("Custom method called.");
}
}
}
服务类 (ServiceClass.java)
@Service
public class ServiceClass {
public void doSomething() {
System.out.println("Doing something...");
}
}
使用引入
@Service
public class AnotherClass {
@Autowired
private ServiceClass serviceClass;
public void useService() {
serviceClass.doSomething();
serviceClass.myInterface.customMethod(); // 通过引入添加的方法
}
}
9.2.自定义拦截器
-
定义:自定义拦截器允许开发者创建自己的拦截器类,以实现特定的横切关注点逻辑。拦截器可以应用于环绕通知中,以执行自定义的行为。
-
示例:展示如何创建自定义拦截器。
自定义拦截器 (CustomInterceptor.java)
public class CustomInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("CustomInterceptor: Before method execution");
Object result = invocation.proceed();
System.out.println("CustomInterceptor: After method execution");
return result;
}
}
切面类 (CustomInterceptorAspect.java)
@Aspect
@Component
public class CustomInterceptorAspect {
@Autowired
private CustomInterceptor customInterceptor;
@Around("@annotation(com.example.annotation.Custom)")
public Object applyCustomInterceptor(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Custom custom = method.getAnnotation(Custom.class);
if (custom != null) {
return customInterceptor.invoke(new ReflectiveMethodInvocation(
joinPoint.getThis(),
method,
joinPoint.getArgs()
));
} else {
return joinPoint.proceed();
}
}
}
自定义注解 (Custom.java)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Custom {}
服务类 (ServiceClass.java)
@Service
public class ServiceClass {
@Custom
public void doSomething() {
System.out.println("Doing something...");
}
}
9.3.异常处理
-
定义:异常处理是 AOP 中的重要组成部分,允许开发者在方法抛出异常时执行特定的逻辑。
-
示例:展示如何使用 Spring AOP 处理异常。
异常处理切面 (ExceptionHandlingAspect.java)
@Aspect
@Component
public class ExceptionHandlingAspect {
@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
public void handleException(JoinPoint joinPoint, Exception ex) {
System.out.println("ExceptionHandlingAspect: " + ex.getMessage());
}
}