SpringBeanContainer falls back to Hibernate's default producer

Issue: SPR-17010
This commit is contained in:
Juergen Hoeller 2018-07-05 17:54:07 +02:00
parent 620e83c35d
commit d2eb4d2671
1 changed files with 46 additions and 19 deletions

View File

@ -19,10 +19,13 @@ package org.springframework.orm.hibernate5;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.resource.beans.container.spi.BeanContainer; import org.hibernate.resource.beans.container.spi.BeanContainer;
import org.hibernate.resource.beans.container.spi.ContainedBean; import org.hibernate.resource.beans.container.spi.ContainedBean;
import org.hibernate.resource.beans.spi.BeanInstanceProducer; import org.hibernate.resource.beans.spi.BeanInstanceProducer;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -72,6 +75,8 @@ import org.springframework.util.ConcurrentReferenceHashMap;
*/ */
public final class SpringBeanContainer implements BeanContainer { public final class SpringBeanContainer implements BeanContainer {
private static final Log logger = LogFactory.getLog(SpringBeanContainer.class);
private final ConfigurableListableBeanFactory beanFactory; private final ConfigurableListableBeanFactory beanFactory;
private final Map<Object, SpringContainedBean<?>> beanCache = new ConcurrentReferenceHashMap<>(); private final Map<Object, SpringContainedBean<?>> beanCache = new ConcurrentReferenceHashMap<>();
@ -96,12 +101,12 @@ public final class SpringBeanContainer implements BeanContainer {
if (lifecycleOptions.canUseCachedReferences()) { if (lifecycleOptions.canUseCachedReferences()) {
bean = this.beanCache.get(beanType); bean = this.beanCache.get(beanType);
if (bean == null) { if (bean == null) {
bean = createBean(beanType, lifecycleOptions); bean = createBean(beanType, lifecycleOptions, fallbackProducer);
this.beanCache.put(beanType, bean); this.beanCache.put(beanType, bean);
} }
} }
else { else {
bean = createBean(beanType, lifecycleOptions); bean = createBean(beanType, lifecycleOptions, fallbackProducer);
} }
return (SpringContainedBean<B>) bean; return (SpringContainedBean<B>) bean;
} }
@ -119,12 +124,12 @@ public final class SpringBeanContainer implements BeanContainer {
if (lifecycleOptions.canUseCachedReferences()) { if (lifecycleOptions.canUseCachedReferences()) {
bean = this.beanCache.get(name); bean = this.beanCache.get(name);
if (bean == null) { if (bean == null) {
bean = createBean(name, beanType, lifecycleOptions); bean = createBean(name, beanType, lifecycleOptions, fallbackProducer);
this.beanCache.put(name, bean); this.beanCache.put(name, bean);
} }
} }
else { else {
bean = createBean(name, beanType, lifecycleOptions); bean = createBean(name, beanType, lifecycleOptions, fallbackProducer);
} }
return (SpringContainedBean<B>) bean; return (SpringContainedBean<B>) bean;
} }
@ -136,26 +141,48 @@ public final class SpringBeanContainer implements BeanContainer {
} }
private SpringContainedBean<?> createBean(Class<?> beanType, LifecycleOptions lifecycleOptions) { private SpringContainedBean<?> createBean(
if (lifecycleOptions.useJpaCompliantCreation()) { Class<?> beanType, LifecycleOptions lifecycleOptions, BeanInstanceProducer fallbackProducer) {
return new SpringContainedBean<>(
this.beanFactory.createBean(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false), try {
this.beanFactory::destroyBean); if (lifecycleOptions.useJpaCompliantCreation()) {
return new SpringContainedBean<>(
this.beanFactory.createBean(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false),
this.beanFactory::destroyBean);
}
else {
return new SpringContainedBean<>(this.beanFactory.getBean(beanType));
}
} }
else { catch (BeanCreationException ex) {
return new SpringContainedBean<>(this.beanFactory.getBean(beanType)); if (logger.isDebugEnabled()) {
logger.debug("Falling back to Hibernate's default producer after bean creation failure for " +
beanType + ": " + ex);
}
return new SpringContainedBean<>(fallbackProducer.produceBeanInstance(beanType));
} }
} }
private SpringContainedBean<?> createBean(String name, Class<?> beanType, LifecycleOptions lifecycleOptions) { private SpringContainedBean<?> createBean(
if (lifecycleOptions.useJpaCompliantCreation()) { String name, Class<?> beanType, LifecycleOptions lifecycleOptions, BeanInstanceProducer fallbackProducer) {
Object bean = this.beanFactory.autowire(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
this.beanFactory.applyBeanPropertyValues(bean, name); try {
this.beanFactory.initializeBean(bean, name); if (lifecycleOptions.useJpaCompliantCreation()) {
return new SpringContainedBean<>(bean, beanInstance -> this.beanFactory.destroyBean(name, beanInstance)); Object bean = this.beanFactory.autowire(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
this.beanFactory.applyBeanPropertyValues(bean, name);
this.beanFactory.initializeBean(bean, name);
return new SpringContainedBean<>(bean, beanInstance -> this.beanFactory.destroyBean(name, beanInstance));
}
else {
return new SpringContainedBean<>(this.beanFactory.getBean(name, beanType));
}
} }
else { catch (BeanCreationException ex) {
return new SpringContainedBean<>(this.beanFactory.getBean(name, beanType)); if (logger.isDebugEnabled()) {
logger.debug("Falling back to Hibernate's default producer after bean creation failure for " +
beanType + ": " + ex);
}
return new SpringContainedBean<>(fallbackProducer.produceBeanInstance(name, beanType));
} }
} }