Skip to content

Spring AOP 编程式创建 @AspectJ 代理 ⚙️

什么是编程式代理创建? 🤔

在 Spring AOP 的世界里,我们通常通过配置文件或注解来声明切面,让 Spring 容器自动为我们创建代理对象。但有时候,我们需要在运行时动态地、手动地创建代理对象,这就是编程式代理创建

NOTE

编程式代理创建让我们能够在代码中直接控制代理的创建过程,而不依赖于 Spring 容器的自动配置。

为什么需要编程式代理创建? 💡

想象一下这些场景:

  1. 动态业务逻辑:你的应用需要根据运行时条件决定是否应用某个切面
  2. 第三方对象增强:你需要为不受 Spring 管理的第三方库对象添加切面功能
  3. 测试场景:在单元测试中,你想为特定对象快速添加监控或日志功能
  4. 插件化架构:动态加载的模块需要在运行时为对象添加横切关注点

TIP

如果把 Spring 容器的自动代理比作"工厂流水线",那么编程式代理创建就像是"手工定制"——更灵活,但需要你亲自动手。

AspectJProxyFactory 核心原理 ⚙️

AspectJProxyFactory 是 Spring 提供的编程式代理创建工具,它的工作流程如下:

基础使用示例 🚀

让我们通过一个实际的例子来理解编程式代理创建:

1. 定义目标对象和接口

kotlin
// 业务接口
interface UserService {
    fun createUser(username: String): String
    fun deleteUser(userId: Long): Boolean
}

// 目标实现类
class UserServiceImpl : UserService {
    override fun createUser(username: String): String {
        println("创建用户: $username") 
        return "用户 $username 创建成功"
    }
    
    override fun deleteUser(userId: Long): Boolean {
        println("删除用户: $userId") 
        return true
    }
}

2. 创建切面

kotlin
import org.aspectj.lang.annotation.*
import org.springframework.stereotype.Component

@Aspect
class SecurityAspect {
    
    @Before("execution(* UserService.*(..))")
    fun checkPermission() {
        println("🔒 执行权限检查...") 
    }
    
    @After("execution(* UserService.*(..))")
    fun logOperation() {
        println("📝 记录操作日志...") 
    }
}

@Aspect  
class PerformanceAspect {
    
    @Around("execution(* UserService.*(..))")
    fun measureTime(joinPoint: ProceedingJoinPoint): Any? {
        val startTime = System.currentTimeMillis()
        println("⏱️ 开始计时...") 
        
        val result = joinPoint.proceed()
        
        val endTime = System.currentTimeMillis()
        println("⏱️ 方法执行耗时: ${endTime - startTime}ms") 
        
        return result
    }
}

3. 编程式创建代理

kotlin
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory

fun main() {
    // 创建目标对象
    val targetObject = UserServiceImpl()
    
    // 创建代理工厂
    val factory = AspectJProxyFactory(targetObject) 
    
    // 添加切面(可以添加多个)
    factory.addAspect(SecurityAspect::class.java) 
    factory.addAspect(PerformanceAspect::class.java) 
    
    // 也可以添加切面实例
    val customAspect = SecurityAspect()
    factory.addAspect(customAspect) 
    
    // 获取代理对象
    val proxy = factory.getProxy<UserService>() 
    
    // 使用代理对象
    println("=== 调用 createUser ===")
    proxy.createUser("张三")
    
    println("\n=== 调用 deleteUser ===")  
    proxy.deleteUser(1001L)
}

IMPORTANT

注意:addAspect() 方法既可以接受切面类(Class),也可以接受切面实例(Object)。使用实例的好处是可以预先配置切面的状态。

高级应用场景 ⭐

场景1:动态切面选择

kotlin
class DynamicProxyCreator {
    
    fun createUserServiceProxy(
        target: UserService,
        enableSecurity: Boolean = true,
        enablePerformance: Boolean = true,
        enableLogging: Boolean = false
    ): UserService {
        
        val factory = AspectJProxyFactory(target)
        
        // 根据条件动态添加切面
        if (enableSecurity) {
            factory.addAspect(SecurityAspect::class.java) 
        }
        
        if (enablePerformance) {
            factory.addAspect(PerformanceAspect::class.java) 
        }
        
        if (enableLogging) {
            factory.addAspect(LoggingAspect::class.java) 
        }
        
        return factory.getProxy()
    }
}

// 使用示例
fun demonstrateDynamicProxy() {
    val creator = DynamicProxyCreator()
    val target = UserServiceImpl()
    
    // 只启用安全检查
    val secureProxy = creator.createUserServiceProxy(
        target = target,
        enableSecurity = true,
        enablePerformance = false
    )
    
    secureProxy.createUser("李四")
}

场景2:为第三方对象添加监控

kotlin
// 假设这是一个第三方库的类,我们无法修改
class ThirdPartyService {
    fun processData(data: String): String {
        Thread.sleep(100) // 模拟处理时间
        return "处理结果: $data"
    }
}

// 为第三方服务添加监控切面
@Aspect
class MonitoringAspect {
    
    @Around("execution(* ThirdPartyService.*(..))")
    fun monitor(joinPoint: ProceedingJoinPoint): Any? {
        val methodName = joinPoint.signature.name
        println("📊 开始监控方法: $methodName") 
        
        try {
            val result = joinPoint.proceed()
            println("✅ 方法执行成功: $methodName") 
            return result
        } catch (e: Exception) {
            println("❌ 方法执行失败: $methodName, 错误: ${e.message}") 
            throw e
        }
    }
}

fun enhanceThirdPartyService() {
    val thirdPartyService = ThirdPartyService()
    
    // 为第三方服务创建增强代理
    val factory = AspectJProxyFactory(thirdPartyService)
    factory.addAspect(MonitoringAspect::class.java)
    
    val enhancedService = factory.getProxy<ThirdPartyService>() 
    
    // 使用增强后的服务
    val result = enhancedService.processData("重要数据")
    println("最终结果: $result")
}

与声明式 AOP 的对比 ⚖️

kotlin
// 编程式创建代理
fun createProgrammaticProxy(): UserService {
    val target = UserServiceImpl()
    val factory = AspectJProxyFactory(target)
    
    // 完全控制何时添加哪些切面
    factory.addAspect(SecurityAspect::class.java) 
    factory.addAspect(PerformanceAspect::class.java) 
    
    return factory.getProxy()
}
kotlin
// 声明式配置(注解方式)
@Service
class UserServiceImpl : UserService {
    // Spring 容器自动创建代理
    override fun createUser(username: String): String {
        return "用户 $username 创建成功"
    }
}

@Aspect
@Component  
class SecurityAspect {
    @Before("execution(* UserService.*(..))")
    fun checkPermission() {
        println("执行权限检查...")
    }
}
特性编程式方式声明式方式
灵活性✅ 高度灵活,运行时决定❌ 编译时确定
简便性❌ 需要手动编码✅ 配置简单
性能⚡ 按需创建⚡ 容器启动时创建
适用场景动态需求、第三方对象常规业务逻辑

最佳实践与注意事项 ⚠️

1. 代理对象的生命周期管理

WARNING

编程式创建的代理对象不受 Spring 容器管理,需要手动管理其生命周期。

kotlin
class ProxyManager {
    private val proxyCache = mutableMapOf<String, Any>()
    
    fun <T> getOrCreateProxy(
        key: String,
        target: T,
        aspectClasses: List<Class<*>>
    ): T {
        return proxyCache.getOrPut(key) {
            val factory = AspectJProxyFactory(target!!)
            aspectClasses.forEach { factory.addAspect(it) }
            factory.getProxy<T>()
        } as T
    }
    
    fun clearCache() {
        proxyCache.clear() 
    }
}

2. 切面实例的重用

TIP

当使用切面实例时,考虑重用实例以节省内存。

kotlin
object AspectInstanceManager {
    private val securityAspect = SecurityAspect()
    private val performanceAspect = PerformanceAspect()
    
    fun createOptimizedProxy(target: UserService): UserService {
        val factory = AspectJProxyFactory(target)
        
        // 重用切面实例
        factory.addAspect(securityAspect) 
        factory.addAspect(performanceAspect) 
        
        return factory.getProxy()
    }
}

3. 异常处理

kotlin
fun safeCreateProxy(target: Any, aspects: List<Class<*>>): Any? {
    return try {
        val factory = AspectJProxyFactory(target)
        aspects.forEach { aspect ->
            try {
                factory.addAspect(aspect) 
            } catch (e: Exception) {
                println("添加切面失败: ${aspect.simpleName}, 错误: ${e.message}") 
                // 可以选择跳过这个切面或者抛出异常
            }
        }
        factory.getProxy<Any>()
    } catch (e: Exception) {
        println("创建代理失败: ${e.message}") 
        null
    }
}

实际业务应用示例 💼

让我们看一个更贴近实际业务的例子:

完整的业务监控代理示例
kotlin
// 业务服务接口
interface OrderService {
    fun createOrder(userId: Long, productId: Long, quantity: Int): String
    fun cancelOrder(orderId: Long): Boolean
}

// 业务服务实现
class OrderServiceImpl : OrderService {
    override fun createOrder(userId: Long, productId: Long, quantity: Int): String {
        // 模拟业务逻辑
        Thread.sleep(50)
        return "订单创建成功,订单号: ${System.currentTimeMillis()}"
    }
    
    override fun cancelOrder(orderId: Long): Boolean {
        Thread.sleep(30)
        return true
    }
}

// 业务监控切面
@Aspect
class BusinessMonitoringAspect {
    
    @Around("execution(* OrderService.*(..))")
    fun monitorBusiness(joinPoint: ProceedingJoinPoint): Any? {
        val methodName = joinPoint.signature.name
        val args = joinPoint.args
        
        println("🔍 业务监控 - 方法: $methodName, 参数: ${args.contentToString()}")
        
        val startTime = System.currentTimeMillis()
        
        return try {
            val result = joinPoint.proceed()
            val duration = System.currentTimeMillis() - startTime
            
            println("✅ 业务成功 - 方法: $methodName, 耗时: ${duration}ms")
            result
        } catch (e: Exception) {
            val duration = System.currentTimeMillis() - startTime
            println("❌ 业务失败 - 方法: $methodName, 耗时: ${duration}ms, 错误: ${e.message}")
            throw e
        }
    }
}

// 业务代理工厂
class BusinessProxyFactory {
    
    fun createMonitoredOrderService(): OrderService {
        val target = OrderServiceImpl()
        val factory = AspectJProxyFactory(target)
        
        // 添加业务监控
        factory.addAspect(BusinessMonitoringAspect::class.java)
        
        return factory.getProxy()
    }
}

// 使用示例
fun main() {
    val proxyFactory = BusinessProxyFactory()
    val orderService = proxyFactory.createMonitoredOrderService()
    
    // 执行业务操作
    println("=== 创建订单 ===")
    val orderResult = orderService.createOrder(1001L, 2001L, 2)
    println("结果: $orderResult")
    
    println("\n=== 取消订单 ===")
    val cancelResult = orderService.cancelOrder(12345L)
    println("结果: $cancelResult")
}

总结 🎉

编程式创建 @AspectJ 代理为我们提供了强大的运行时 AOP 能力:

IMPORTANT

核心价值

  • 🎯 动态性:运行时决定切面应用策略
  • 🔧 灵活性:完全控制代理创建过程
  • 🚀 扩展性:为任意对象添加横切关注点
  • 🧪 测试友好:便于单元测试和集成测试

适用场景

  • 需要根据运行时条件动态应用切面
  • 为第三方库对象添加 AOP 功能
  • 插件化架构中的动态功能增强
  • 测试环境中的快速功能验证

关键要点

  • 使用 AspectJProxyFactory 创建代理
  • 支持添加切面类和切面实例
  • 需要手动管理代理对象生命周期
  • 与声明式 AOP 形成互补

通过掌握编程式代理创建,你将拥有更强大的 AOP 工具箱,能够应对各种复杂的业务场景! 💪