From 1bde920cce0eb6b7d0db60a604eb34d57747e1c7 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 8 Mar 2018 18:13:00 +0100 Subject: [PATCH] Quick access to volatile field (full synchronization only for lazy init) Issue: SPR-16570 (cherry picked from commit 50253f6) --- .../AbstractBeanFactoryBasedTargetSource.java | 35 +++++++++++-------- .../jdbc/support/JdbcAccessor.java | 30 ++++++++++------ 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java index 3d0e9ae4f5a..b070b628ead 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (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; /** Class of the target */ - private Class targetClass; + private volatile Class targetClass; /** * BeanFactory that owns this TargetSource. We need to hold onto this @@ -120,21 +120,28 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour @Override - public synchronized Class getTargetClass() { - if (this.targetClass == null && this.beanFactory != null) { - // Determine type of the target bean. - this.targetClass = this.beanFactory.getType(this.targetBeanName); - if (this.targetClass == null) { - if (logger.isTraceEnabled()) { - logger.trace("Getting bean with name '" + this.targetBeanName + "' in order to determine type"); - } - Object beanInstance = this.beanFactory.getBean(this.targetBeanName); - if (beanInstance != null) { - this.targetClass = beanInstance.getClass(); + public Class getTargetClass() { + Class targetClass = this.targetClass; + if (targetClass != null) { + return targetClass; + } + synchronized (this) { + // Full check within synchronization, entering the BeanFactory interaction algorithm only once... + targetClass = this.targetClass; + if (targetClass == null && this.beanFactory != null) { + // 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 diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java index f383a4d8339..f43a4478161 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,7 +42,7 @@ public abstract class JdbcAccessor implements InitializingBean { private DataSource dataSource; - private SQLExceptionTranslator exceptionTranslator; + private volatile SQLExceptionTranslator exceptionTranslator; private boolean lazyInit = true; @@ -92,17 +92,25 @@ public abstract class JdbcAccessor implements InitializingBean { * {@link SQLStateSQLExceptionTranslator} in case of no DataSource. * @see #getDataSource() */ - public synchronized SQLExceptionTranslator getExceptionTranslator() { - if (this.exceptionTranslator == null) { - DataSource dataSource = getDataSource(); - if (dataSource != null) { - this.exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); - } - else { - this.exceptionTranslator = new SQLStateSQLExceptionTranslator(); + public SQLExceptionTranslator getExceptionTranslator() { + SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator; + if (exceptionTranslator != null) { + return exceptionTranslator; + } + synchronized (this) { + exceptionTranslator = this.exceptionTranslator; + 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; } /**