内容提要
在Spring AOP中,被代理对象通常是单例的。通过ProxyFactory创建代理时,setTarget方法使用SingletonTargetSource,确保多个代理持有相同的被代理对象。TargetSource接口有多种实现,决定了被代理对象的生命周期,包括SingletonTargetSource、SimpleBeanTargetSource和LazyInitTargetSource,后者支持延迟初始化。理解这些概念对使用@Scope注解至关重要。
延伸解读
TargetSource 决定被代理对象的生命周期
在 Spring AOP 中,被代理对象是否单例并非由代理对象本身决定,而是由 TargetSource 实现类控制。TargetSource 接口的 isStatic 方法返回 true 时,表示被代理对象是单例的,无需调用 releaseTarget 释放;返回 false 则需在使用后释放。因此,理解 TargetSource 的不同实现,是掌握被代理对象生命周期的关键。
编程式代理默认使用单例目标源
通过 ProxyFactory 的 setTarget 方法设置目标对象时,内部会创建 SingletonTargetSource。这意味着无论从同一个 ProxyFactory 获取多少个代理对象,它们持有的被代理对象都是同一个实例。但代理对象本身可以是不同的,例如多次调用 getProxy 会生成不同的代理实例,但目标对象共享。
SimpleBeanTargetSource 与容器作用域联动
SimpleBeanTargetSource 每次调用 getTarget 时都从 Spring 容器获取 Bean,因此被代理对象是否为单例完全由容器控制。如果目标 Bean 配置为 prototype 作用域,那么每次获取的代理对象所持有的目标对象可能不同。这为 @Scope 注解的高级用法提供了基础,开发者需注意容器作用域对代理行为的影响。
LazyInitTargetSource 的延迟初始化特性
LazyInitTargetSource 同样从容器获取 Bean,但支持延迟初始化:首次调用 getTarget 时才真正获取目标对象,并缓存起来。这适用于需要延迟加载的场景,但需注意其 isStatic 方法继承自父类,返回 false,因此每次使用后仍需调用 releaseTarget,尽管当前实现中该方法为空。
Q&A
在Spring AOP中,被代理对象通常是什么类型?
在Spring AOP中,被代理对象通常是单例的。
如何确保多个代理持有相同的被代理对象?
通过ProxyFactory创建代理时,setTarget方法使用SingletonTargetSource来确保多个代理持有相同的被代理对象。
TargetSource接口有哪些实现类?
TargetSource接口有多种实现类,包括SingletonTargetSource、SimpleBeanTargetSource和LazyInitTargetSource。
什么情况下使用SimpleBeanTargetSource?
使用SimpleBeanTargetSource时,每次需要被代理对象时会从Spring容器中查找相应的Bean,是否为单例由Spring容器控制。
LazyInitTargetSource的特点是什么?
LazyInitTargetSource支持延迟初始化,首次调用时才获取被代理对象。
SingletonTargetSource的isStatic方法返回什么?
SingletonTargetSource的isStatic方法返回true,表示被代理对象是单例的。