Java实现AOP案例代码

wen java案例 4

本文目录导读:

Java实现AOP案例代码

  1. Spring AOP实现(基于注解)
  2. Spring AOP基于XML配置(传统方式)
  3. 原生JDK动态代理实现(不用框架)
  4. CGLIB代理实现(无需接口)
  5. 实际应用案例:事务管理切面
  6. 性能监控切面

我为您提供几种Java实现AOP的典型案例代码,包括Spring AOP和原生动态代理两种方式:

Spring AOP实现(基于注解)

添加依赖(pom.xml)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
</dependencies>

自定义日志切面

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAspect {
    // 定义切点:所有service包下的所有方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void servicePointcut() {}
    // 前置通知
    @Before("servicePointcut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("执行前:方法名:" + joinPoint.getSignature().getName());
        System.out.println("参数:" + Arrays.toString(joinPoint.getArgs()));
    }
    // 后置通知(方法正常执行后)
    @AfterReturning(pointcut = "servicePointcut()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("执行后:返回结果:" + result);
    }
    // 异常通知
    @AfterThrowing(pointcut = "servicePointcut()", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Exception exception) {
        System.out.println("异常通知:异常信息:" + exception.getMessage());
    }
    // 环绕通知
    @Around("servicePointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知-开始");
        long startTime = System.currentTimeMillis();
        try {
            Object result = pjp.proceed(); // 执行目标方法
            return result;
        } catch (Exception e) {
            throw e;
        } finally {
            long endTime = System.currentTimeMillis();
            System.out.println("环绕通知-结束,执行时间:" + (endTime - startTime) + "ms");
        }
    }
}

业务服务类

import org.springframework.stereotype.Service;
@Service
public class UserService {
    public String getUserInfo(String username) {
        System.out.println("业务方法:查询用户信息");
        if (username == null) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        return "用户:" + username;
    }
    public void deleteUser(int userId) {
        System.out.println("业务方法:删除用户ID=" + userId);
    }
}

Spring AOP基于XML配置(传统方式)

切面类

import org.aspectj.lang.ProceedingJoinPoint;
public class LogAspectXml {
    public void beforeMethod(ProceedingJoinPoint pjp) {
        System.out.println("XML配置前置通知");
    }
    public void afterMethod(ProceedingJoinPoint pjp) {
        System.out.println("XML配置后置通知");
    }
    public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("XML环绕通知-开始");
        Object result = pjp.proceed();
        System.out.println("XML环绕通知-结束");
        return result;
    }
}

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"
       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">
    <!-- 业务类 -->
    <bean id="userService" class="com.example.service.UserService"/>
    <!-- 切面类 -->
    <bean id="logAspect" class="com.example.aspect.LogAspectXml"/>
    <!-- AOP配置 -->
    <aop:config>
        <aop:aspect ref="logAspect">
            <!-- 定义切点 -->
            <aop:pointcut id="servicePointcut" 
                         expression="execution(* com.example.service.*.*(..))"/>
            <!-- 前置通知 -->
            <aop:before method="beforeMethod" pointcut-ref="servicePointcut"/>
            <!-- 后置通知 -->
            <aop:after method="afterMethod" pointcut-ref="servicePointcut"/>
            <!-- 环绕通知 -->
            <aop:around method="aroundMethod" pointcut-ref="servicePointcut"/>
        </aop:aspect>
    </aop:config>
</beans>

原生JDK动态代理实现(不用框架)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Date;
public class LogProxy implements InvocationHandler {
    private Object target;
    public LogProxy(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK代理-方法执行前:" + new Date());
        // 调用目标方法
        Object result = method.invoke(target, args);
        System.out.println("JDK代理-方法执行后:" + new Date());
        return result;
    }
    // 获取代理对象
    @SuppressWarnings("unchecked")
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }
}
// 接口
interface UserServiceInterface {
    String getUserInfo(String username);
    void deleteUser(int userId);
}
// 实现类
class UserServiceImpl implements UserServiceInterface {
    @Override
    public String getUserInfo(String username) {
        System.out.println("业务实现:查询用户信息");
        return "用户:" + username;
    }
    @Override
    public void deleteUser(int userId) {
        System.out.println("业务实现:删除用户ID=" + userId);
    }
}
// 使用示例
public class ProxyDemo {
    public static void main(String[] args) {
        UserServiceInterface target = new UserServiceImpl();
        LogProxy logProxy = new LogProxy(target);
        UserServiceInterface proxy = logProxy.getProxy();
        // 调用代理方法
        String userInfo = proxy.getUserInfo("张三");
        System.out.println("返回结果:" + userInfo);
        proxy.deleteUser(1);
    }
}

CGLIB代理实现(无需接口)

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) 
            throws Throwable {
        System.out.println("CGLIB代理-方法执行前");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("CGLIB代理-方法执行后");
        return result;
    }
    // 创建代理对象
    @SuppressWarnings("unchecked")
    public <T> T createProxy(Class<T> targetClass) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetClass);
        enhancer.setCallback(this);
        return (T) enhancer.create();
    }
}
// 测试类(无需接口)
class ProductService {
    public String getProductInfo(String name) {
        System.out.println("商品服务:获取商品信息");
        return "商品:" + name;
    }
    public void deleteProduct(int productId) {
        System.out.println("商品服务:删除商品ID=" + productId);
    }
}
// 使用示例
public class CglibDemo {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        ProductService productService = proxy.createProxy(ProductService.class);
        String result = productService.getProductInfo("手机");
        System.out.println("返回结果:" + result);
        productService.deleteProduct(100);
    }
}

实际应用案例:事务管理切面

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
@Aspect
@Component
public class TransactionAspect {
    // 使用Spring事务模板
    @Around("@annotation(tx)") // 使用自定义注解标记
    public Object manageTransaction(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("事务开始");
        try {
            // 伪事务操作
            Object result = pjp.proceed();
            System.out.println("事务提交");
            return result;
        } catch (Exception e) {
            System.out.println("事务回滚");
            throw e;
        } finally {
            System.out.println("事务结束");
        }
    }
}
// 自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTransaction {
}
// 使用示例
@Service
public class OrderService {
    @MyTransaction
    public void createOrder(String orderNo) {
        System.out.println("创建订单:" + orderNo);
        // 业务逻辑
    }
    @MyTransaction
    public void updateOrder(Long orderId) {
        System.out.println("更新订单:" + orderId);
        // 业务逻辑
    }
}

性能监控切面

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class PerformanceMonitor {
    @Around("execution(* com.example.service.*.*(..))")
    public Object monitorPerformance(ProceedingJoinPoint pjp) throws Throwable {
        String methodName = pjp.getSignature().getName();
        String className = pjp.getTarget().getClass().getSimpleName();
        long start = System.currentTimeMillis();
        try {
            Object result = pjp.proceed();
            long executionTime = System.currentTimeMillis() - start;
            System.out.println(String.format(
                "方法%s.%s执行时间:%d ms", className, methodName, executionTime));
            // 检查性能阈值
            if (executionTime > 1000) {
                System.err.println(String.format(
                    "警告:方法%s.%s执行过慢!", className, methodName));
            }
            return result;
        } catch (Throwable t) {
            long executionTime = System.currentTimeMillis() - start;
            System.err.println(String.format(
                "方法%s.%s执行异常,耗时:%d ms", className, methodName, executionTime));
            throw t;
        }
    }
}
  1. Spring AOP:最常用,支持注解和XML配置,适合企业应用
  2. JDK动态代理:基于接口,轻量级
  3. CGLIB代理:基于继承,无需接口
  4. 性能监控、事务管理:实际应用中的典型场景

选择建议:

  • 项目使用Spring框架:优先选择Spring AOP注解方式
  • 简单场景:使用JDK动态代理或CGLIB
  • 需要高级特性(如拦截器链):考虑AspectJ

抱歉,评论功能暂时关闭!