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 7cf1c0d1b3..b070b628ea 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-2017 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,19 +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); - 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 ec93e741d5..17350cfbf3 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-2017 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. @@ -46,7 +46,7 @@ public abstract class JdbcAccessor implements InitializingBean { private DataSource dataSource; @Nullable - private SQLExceptionTranslator exceptionTranslator; + private volatile SQLExceptionTranslator exceptionTranslator; private boolean lazyInit = true; @@ -109,17 +109,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; } /**