Quick access to volatile field (full synchronization only for lazy init)

Issue: SPR-16570
This commit is contained in:
Juergen Hoeller 2018-03-08 18:13:00 +01:00
parent 139dc1d373
commit 50253f670e
2 changed files with 43 additions and 26 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -60,7 +60,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
private String targetBeanName; private String targetBeanName;
/** Class of the target */ /** Class of the target */
private Class<?> targetClass; private volatile Class<?> targetClass;
/** /**
* BeanFactory that owns this TargetSource. We need to hold onto this * BeanFactory that owns this TargetSource. We need to hold onto this
@ -120,19 +120,28 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
@Override @Override
public synchronized Class<?> getTargetClass() { public Class<?> getTargetClass() {
if (this.targetClass == null && this.beanFactory != null) { Class<?> targetClass = this.targetClass;
// Determine type of the target bean. if (targetClass != null) {
this.targetClass = this.beanFactory.getType(this.targetBeanName); return targetClass;
if (this.targetClass == null) { }
if (logger.isTraceEnabled()) { synchronized (this) {
logger.trace("Getting bean with name '" + this.targetBeanName + "' in order to determine type"); // Full check within synchronization, entering the BeanFactory interaction algorithm only once...
} targetClass = this.targetClass;
Object beanInstance = this.beanFactory.getBean(this.targetBeanName); if (targetClass == null && this.beanFactory != null) {
this.targetClass = beanInstance.getClass(); // Determine type of the target bean.
} targetClass = this.beanFactory.getType(this.targetBeanName);
if (targetClass == null) {
if (logger.isTraceEnabled()) {
logger.trace("Getting bean with name '" + this.targetBeanName + "' for type determination");
}
Object beanInstance = this.beanFactory.getBean(this.targetBeanName);
targetClass = beanInstance.getClass();
}
this.targetClass = targetClass;
}
return targetClass;
} }
return this.targetClass;
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -46,7 +46,7 @@ public abstract class JdbcAccessor implements InitializingBean {
private DataSource dataSource; private DataSource dataSource;
@Nullable @Nullable
private SQLExceptionTranslator exceptionTranslator; private volatile SQLExceptionTranslator exceptionTranslator;
private boolean lazyInit = true; private boolean lazyInit = true;
@ -109,17 +109,25 @@ public abstract class JdbcAccessor implements InitializingBean {
* {@link SQLStateSQLExceptionTranslator} in case of no DataSource. * {@link SQLStateSQLExceptionTranslator} in case of no DataSource.
* @see #getDataSource() * @see #getDataSource()
*/ */
public synchronized SQLExceptionTranslator getExceptionTranslator() { public SQLExceptionTranslator getExceptionTranslator() {
if (this.exceptionTranslator == null) { SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator;
DataSource dataSource = getDataSource(); if (exceptionTranslator != null) {
if (dataSource != null) { return exceptionTranslator;
this.exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); }
} synchronized (this) {
else { exceptionTranslator = this.exceptionTranslator;
this.exceptionTranslator = new SQLStateSQLExceptionTranslator(); if (exceptionTranslator == null) {
} DataSource dataSource = getDataSource();
if (dataSource != null) {
exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource);
}
else {
exceptionTranslator = new SQLStateSQLExceptionTranslator();
}
this.exceptionTranslator = exceptionTranslator;
}
return exceptionTranslator;
} }
return this.exceptionTranslator;
} }
/** /**