这篇文章将为大家详细讲解有关Springboot中TargetSource的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
在柯桥等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都做网站、网站建设 网站设计制作按需制作网站,公司网站建设,企业网站建设,成都品牌网站建设,成都全网营销推广,成都外贸网站制作,柯桥网站建设费用合理。
摘要:
其实proxy代理的不是target,而是TargetSource,这点非常重要,一定要分清楚!!!
通常情况下,一个代理对象只能代理一个target,每次方法调用的目标也是唯一固定的target。但是,如果让proxy代理TargetSource,可以使得每次方法调用的target实例都不同(当然也可以相同,这取决于TargetSource实现)。这种机制使得方法调用变得灵活,可以扩展出很多高级功能,如:单利,原型,本地线程,目标对象池、运行时目标对象热替换目标源等等。

Spring内置的TargetSource
SingletonTargetSource
public class SingletonTargetSource implements TargetSource, Serializable {
/** Target cached and invoked using reflection. */
private final Object target;
//省略无关代码......
@Override
public Object getTarget() {
return this.target;
}
//省略无关代码......
}从这个目标源取得的目标对象是单例的,成员变量target缓存了目标对象,每次getTarget()都是返回这个对象。
PrototypeTargetSource
public class PrototypeTargetSource extends AbstractPrototypeBasedTargetSource {
/**
* Obtain a new prototype instance for every call.
* @see #newPrototypeInstance()
*/
@Override
public Object getTarget() throws BeansException {
return newPrototypeInstance();
}
/**
* Destroy the given independent instance.
* @see #destroyPrototypeInstance
*/
@Override
public void releaseTarget(Object target) {
destroyPrototypeInstance(target);
}
//省略无关代码......
}每次getTarget()将生成prototype类型的bean,即其生成的bean并不是单例的,因而使用这个类型的TargetSource时需要注意,封装的目标bean必须是prototype类型的。PrototypeTargetSource继承了AbstractBeanFactoryBasedTargetSource拥有了创建bean的能力。
public abstract class AbstractPrototypeBasedTargetSource extends AbstractBeanFactoryBasedTargetSource {
//省略无关代码......
/**
* Subclasses should call this method to create a new prototype instance.
* @throws BeansException if bean creation failed
*/
protected Object newPrototypeInstance() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Creating new instance of bean '" + getTargetBeanName() + "'");
}
return getBeanFactory().getBean(getTargetBeanName());
}
/**
* Subclasses should call this method to destroy an obsolete prototype instance.
* @param target the bean instance to destroy
*/
protected void destroyPrototypeInstance(Object target) {
if (logger.isDebugEnabled()) {
logger.debug("Destroying instance of bean '" + getTargetBeanName() + "'");
}
if (getBeanFactory() instanceof ConfigurableBeanFactory) {
((ConfigurableBeanFactory) getBeanFactory()).destroyBean(getTargetBeanName(), target);
}
else if (target instanceof DisposableBean) {
try {
((DisposableBean) target).destroy();
}
catch (Throwable ex) {
logger.warn("Destroy method on bean with name '" + getTargetBeanName() + "' threw an exception", ex);
}
}
}
//省略无关代码......
}可以看到,PrototypeTargetSource的生成prototype类型bean的方式主要是委托给BeanFactory进行的,因为BeanFactory自有一套生成prototype类型的bean的逻辑,因而PrototypeTargetSource也就具有生成prototype类型bean的能力,这也就是我们要生成的目标bean必须声明为prototype类型的原因。
ThreadLocalTargetSource
public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource
implements ThreadLocalTargetSourceStats, DisposableBean {
/**
* ThreadLocal holding the target associated with the current
* thread. Unlike most ThreadLocals, which are static, this variable
* is meant to be per thread per instance of the ThreadLocalTargetSource class.
*/
private final ThreadLocalThreadLocalTargetSource也就是和线程绑定的TargetSource,可以理解,其底层实现必然使用的是ThreadLocal。既然使用了ThreadLocal,也就是说我们需要注意两个问题:
目标对象必须声明为prototype类型,因为每个线程都会持有一个不一样的对象;
目标对象必须是无状态的,因为目标对象是和当前线程绑定的,而Spring是使用的线程池处理的请求,因而每个线程可能处理不同的请求,因而为了避免造成问题,目标对象必须是无状态的。
实现自定义的TargetSource
package com.github.dqqzj.springboot.target;
import org.springframework.aop.TargetSource;
import org.springframework.util.Assert;
import java.lang.reflect.Array;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author qinzhongjian
* @date created in 2019-08-25 12:43
* @description: TODO
* @since JDK 1.8.0_212-b10z
*/
public class DqqzjTargetSource implements TargetSource {
private final AtomicInteger idx = new AtomicInteger();
private final Object[] target;;
public DqqzjTargetSource(Object[] target) {
Assert.notNull(target, "Target object must not be null");
this.target = target;
}
@Override
public Class> getTargetClass() {
return target.getClass();
}
@Override
public boolean isStatic() {
return false;
}
@Override
public Object getTarget() throws Exception {
return this.target[this.idx.getAndIncrement() & this.target.length - 1];
}
@Override
public void releaseTarget(Object target) throws Exception {
}
}实现自定义TargetSource主要有两个点要注意,一个是getTarget()方法,该方法中需要实现获取目标对象的逻辑,另一个是isStatic()方法,这个方法告知Spring是否需要缓存目标对象,在非单例的情况下一般是返回false。
关于Springboot中TargetSource的作用是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
网页名称:Springboot中TargetSource的作用是什么
网页路径:http://www.jxjierui.cn/article/ghsdgd.html


咨询
建站咨询
