我将对象定义为作用域“线程”。
在代码的某些地方,实例是通过@Autowired获得的,而在其他地方是通过上下文getBean()获得的,比较对象时,它们是不同的。
由于对象是“线程”作用域的,所以我希望返回该对象的相同实例。
下面是代码,首先我定义一个自定义范围
@Configuration
public class ThreadScopeRegisteringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerScope("thread", new SimpleThreadScope());
}
}
测试对象定义为:
@Component
@Scope("thread")
public class ThreadScopeObject implements InitializingBean {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadScopeObject.class);
private String field1;
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
@Override
public void afterPropertiesSet() throws Exception {
LOGGER.info("****************** new object - " + this);
}
}
也将服务定义为:
@Service
public class ThreadScopeService {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadScopeService.class);
@Autowired
private ThreadScopeObject threadScopeObject;
public void showObject() {
LOGGER.info ("ShowObject: " + threadScopeObject);
}
}
最后定义了一个异步方法[RunnableService.java]:
@Async
public CompletableFuture<Map> objectInstanceTest() {
ThreadScopeObject o = ApplicationContextHolder.getContext().getBean(ThreadScopeObject.class);
LOGGER.info ("Thread object: " + o);
service.showObject();
return CompletableFuture.completedFuture(new HashMap<>());
}
运行该应用程序时,我收到以下日志:
19:15:27.094 [mcd-async-1] INFO com.mono.threadSample.ThreadScopeObject - ****************** new object - com.mono.threadSample.ThreadScopeObject@69c8f2bb
19:15:27.094 [mcd-async-1] INFO com.mono.threadSample.RunnableService - Thread object: com.mono.threadSample.ThreadScopeObject@69c8f2bb
19:15:27.094 [mcd-async-1] INFO com.mono.threadSample.ThreadScopeService - ShowObject: com.mono.threadSample.ThreadScopeObject@fd0e5b6
我想知道在同一线程中实例化对象“线程”两次的原因。
代码:https://github.com/saavedrah/spring-threadSample
谢谢。
答案 0 :(得分:1)
ThreadScopeService
在默认情况下是单例,因此当它由spring构造时,它将从创建它的线程中获得一个ThreadScopeObject
,并且此后将不会更新。有两种解决方法:
将Provider<ThreadScopeObject>
或ObjectFactory<ThreadScopeObject>
注入ThreadScopeService
中,并在需要时调用其get
方法来检索作用域对象。
用ThreadScopeObject
注释@Scope("thread", proxyMode = ScopedProxyMode.TARGET_CLASS)
。这将使spring在您的对象周围创建一个代理,该代理会将所有调用委派给正确作用域的实例。