TargetSource(目标源)是被代理的target(目标对象)实例的来源。TargetSource被用于获取当前MethodInvocation(方法调用)所需要的目标对象target。换句话说,proxy代理的并不是target,而是targetSource对象。
通常情况下,一个代理对象只能代理一个target,每次方法调用目标也是唯一的target。但是如果让proxy代理TargetSource,可以使得每次方法调用的target实例都不相同。(当然,这取决于TargetSource的实现)。而这种机制,可以使得方法的调用更加灵活。
1. Aop中TargetSource的使用方式
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
//回调方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
...
//(代码1)获取target对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取Advised的过滤器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//若MethodInterceptor的Chain为空时
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 调用拦截器链...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
...
}
finally {
if (target != null && !targetSource.isStatic()) {
//(代码2) 释放Target对象
targetSource.releaseTarget(target);
}
...
}
}
}
2. TargetSource对象结构
public interface TargetSource extends TargetClassAware {
//返回目标类型
Class<?> getTargetClass();
//判断getTarget()返回的是相同对象吗?在这种情况下,不需要调用eleaseTarget(Object)方法。
//若目标对象是不可变的,AOP框架可以缓存getTarget()的返回值
boolean isStatic();
//获取目标对象
Object getTarget() throws Exception;
//释放从getTarget()方法,如果有的情况下。
void releaseTarget(Object target) throws Exception;
}
SpringAOP的自动代理会使用SingletonTargetSource去创建TargetSource对象。
而其他子类的作用一般在手动代理时按需使用。
- 四个简单的使用
- EmptyTargetSource:静态目标源,当不存在target目标对象或者连TargetClass目标类都不存在时使用。
- HotSwappableTargetSource:动态目标源,支持热替换的目标源,支持Spring应用运行时替换目标对象。
- JndiObjectTargetSource:Spring对JNDI管理bean的支持,static可配置。
- SingletonTargetSource:静态对象源,Spring的AOP框架单例bean创建的目标源。换句话说,SingletonTargetSource、proxy和目标bean三者的生命周期均相同。
- 三个抽象类的使用
- AbstractBeanFactoryBasedTargetSource:此类基于IOC容器使用,也就是说target目标对象可以通过beanName从容器中获取,而该类的实现类:
- SimpleBeanTargetSource:直接调用getBean从容器中获取target对象;
- LazyInitTargetSource:延迟加载目标源,子类可重写
postProcessTargetObject
方法; - AbstractPrototypeBasedTargetSource:原型bean目标源,此抽象类可确保beanName对应的bean的scope属性为prototype。其子类为简单原型、池化原型、线程隔离原型这3种实现。
- AbstractRefreshableTargetSource:可刷新的目标源,此类的实现可根据配置的刷新延迟时间,在每次获取对象时自动刷新目标对象。
- AbstractLazyCreationTargetSource:此类是在调用getTarget()获取时才创建目标对象,创建方法由子类实现。