Appearance
Spring AOP 编程式创建 @AspectJ 代理 ⚙️
什么是编程式代理创建? 🤔
在 Spring AOP 的世界里,我们通常通过配置文件或注解来声明切面,让 Spring 容器自动为我们创建代理对象。但有时候,我们需要在运行时动态地、手动地创建代理对象,这就是编程式代理创建。
NOTE
编程式代理创建让我们能够在代码中直接控制代理的创建过程,而不依赖于 Spring 容器的自动配置。
为什么需要编程式代理创建? 💡
想象一下这些场景:
- 动态业务逻辑:你的应用需要根据运行时条件决定是否应用某个切面
- 第三方对象增强:你需要为不受 Spring 管理的第三方库对象添加切面功能
- 测试场景:在单元测试中,你想为特定对象快速添加监控或日志功能
- 插件化架构:动态加载的模块需要在运行时为对象添加横切关注点
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 工具箱,能够应对各种复杂的业务场景! 💪