spring SpringBeanContainer 源码
spring SpringBeanContainer 代码
文件路径:/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.orm.hibernate5;
import java.util.Map;
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.ContainedBean;
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
/**
* Spring's implementation of Hibernate's {@link BeanContainer} SPI,
* delegating to a Spring {@link ConfigurableListableBeanFactory}.
*
* <p>Auto-configured by {@link LocalSessionFactoryBean#setBeanFactory},
* programmatically supported via {@link LocalSessionFactoryBuilder#setBeanContainer},
* and manually configurable through a "hibernate.resource.beans.container" entry
* in JPA properties, e.g.:
*
* <pre class="code">
* <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
* ...
* <property name="jpaPropertyMap">
* <map>
* <entry key="hibernate.resource.beans.container">
* <bean class="org.springframework.orm.hibernate5.SpringBeanContainer"/>
* </entry>
* </map>
* </property>
* </bean></pre>
*
* Or in Java-based JPA configuration:
*
* <pre class="code">
* LocalContainerEntityManagerFactoryBean emfb = ...
* emfb.getJpaPropertyMap().put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
* </pre>
*
* Please note that Spring's {@link LocalSessionFactoryBean} is an immediate alternative
* to {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} for
* common JPA purposes: The Hibernate {@code SessionFactory} will natively expose the JPA
* {@code EntityManagerFactory} interface as well, and Hibernate {@code BeanContainer}
* integration will be registered out of the box.
*
* @author Juergen Hoeller
* @since 5.1
* @see LocalSessionFactoryBean#setBeanFactory
* @see LocalSessionFactoryBuilder#setBeanContainer
* @see org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean#setJpaPropertyMap
* @see org.hibernate.cfg.AvailableSettings#BEAN_CONTAINER
*/
public final class SpringBeanContainer implements BeanContainer {
private static final Log logger = LogFactory.getLog(SpringBeanContainer.class);
private final ConfigurableListableBeanFactory beanFactory;
private final Map<Object, SpringContainedBean<?>> beanCache = new ConcurrentReferenceHashMap<>();
/**
* Instantiate a new SpringBeanContainer for the given bean factory.
* @param beanFactory the Spring bean factory to delegate to
*/
public SpringBeanContainer(ConfigurableListableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "ConfigurableListableBeanFactory is required");
this.beanFactory = beanFactory;
}
@Override
@SuppressWarnings("unchecked")
public <B> ContainedBean<B> getBean(
Class<B> beanType, LifecycleOptions lifecycleOptions, BeanInstanceProducer fallbackProducer) {
SpringContainedBean<?> bean;
if (lifecycleOptions.canUseCachedReferences()) {
bean = this.beanCache.get(beanType);
if (bean == null) {
bean = createBean(beanType, lifecycleOptions, fallbackProducer);
this.beanCache.put(beanType, bean);
}
}
else {
bean = createBean(beanType, lifecycleOptions, fallbackProducer);
}
return (SpringContainedBean<B>) bean;
}
@Override
@SuppressWarnings("unchecked")
public <B> ContainedBean<B> getBean(
String name, Class<B> beanType, LifecycleOptions lifecycleOptions, BeanInstanceProducer fallbackProducer) {
SpringContainedBean<?> bean;
if (lifecycleOptions.canUseCachedReferences()) {
bean = this.beanCache.get(name);
if (bean == null) {
bean = createBean(name, beanType, lifecycleOptions, fallbackProducer);
this.beanCache.put(name, bean);
}
}
else {
bean = createBean(name, beanType, lifecycleOptions, fallbackProducer);
}
return (SpringContainedBean<B>) bean;
}
@Override
public void stop() {
this.beanCache.values().forEach(SpringContainedBean::destroyIfNecessary);
this.beanCache.clear();
}
private SpringContainedBean<?> createBean(
Class<?> beanType, LifecycleOptions lifecycleOptions, BeanInstanceProducer fallbackProducer) {
try {
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));
}
}
catch (BeansException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Falling back to Hibernate's default producer after bean creation failure for " +
beanType + ": " + ex);
}
try {
return new SpringContainedBean<>(fallbackProducer.produceBeanInstance(beanType));
}
catch (RuntimeException ex2) {
if (ex instanceof BeanCreationException) {
if (logger.isDebugEnabled()) {
logger.debug("Fallback producer failed for " + beanType + ": " + ex2);
}
// Rethrow original Spring exception from first attempt.
throw ex;
}
else {
// Throw fallback producer exception since original was probably NoSuchBeanDefinitionException.
throw ex2;
}
}
}
}
private SpringContainedBean<?> createBean(
String name, Class<?> beanType, LifecycleOptions lifecycleOptions, BeanInstanceProducer fallbackProducer) {
try {
if (lifecycleOptions.useJpaCompliantCreation()) {
Object bean = this.beanFactory.autowire(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
this.beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
this.beanFactory.applyBeanPropertyValues(bean, name);
bean = this.beanFactory.initializeBean(bean, name);
return new SpringContainedBean<>(bean, beanInstance -> this.beanFactory.destroyBean(name, beanInstance));
}
else {
return new SpringContainedBean<>(this.beanFactory.getBean(name, beanType));
}
}
catch (BeansException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Falling back to Hibernate's default producer after bean creation failure for " +
beanType + " with name '" + name + "': " + ex);
}
try {
return new SpringContainedBean<>(fallbackProducer.produceBeanInstance(name, beanType));
}
catch (RuntimeException ex2) {
if (ex instanceof BeanCreationException) {
if (logger.isDebugEnabled()) {
logger.debug("Fallback producer failed for " + beanType + " with name '" + name + "': " + ex2);
}
// Rethrow original Spring exception from first attempt.
throw ex;
}
else {
// Throw fallback producer exception since original was probably NoSuchBeanDefinitionException.
throw ex2;
}
}
}
}
private static final class SpringContainedBean<B> implements ContainedBean<B> {
private final B beanInstance;
@Nullable
private Consumer<B> destructionCallback;
public SpringContainedBean(B beanInstance) {
this.beanInstance = beanInstance;
}
public SpringContainedBean(B beanInstance, Consumer<B> destructionCallback) {
this.beanInstance = beanInstance;
this.destructionCallback = destructionCallback;
}
@Override
public B getBeanInstance() {
return this.beanInstance;
}
public void destroyIfNecessary() {
if (this.destructionCallback != null) {
this.destructionCallback.accept(this.beanInstance);
}
}
}
}
相关信息
相关文章
spring ConfigurableJtaPlatform 源码
spring HibernateExceptionTranslator 源码
spring HibernateJdbcException 源码
spring HibernateObjectRetrievalFailureException 源码
spring HibernateOptimisticLockingFailureException 源码
spring HibernateQueryException 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
7、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦