Skip to content

Commit 50ed863

Browse files
committed
EntityManagerFactoryUtils finds default EntityManagerFactory in parent contexts as well
Also introduces consistent use of getBean(Class) for similar use cases across the framework, accepting a locally unique target bean even if further matching beans would be available in parent contexts (in contrast to BeanFactoryUtils.beanOfType's behavior). Issue: SPR-10160
1 parent f9bb4b3 commit 50ed863

File tree

4 files changed

+61
-65
lines changed

4 files changed

+61
-65
lines changed

org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.java

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
2727
import org.springframework.beans.FatalBeanException;
2828
import org.springframework.beans.factory.BeanFactory;
2929
import org.springframework.beans.factory.BeanFactoryAware;
30-
import org.springframework.beans.factory.BeanFactoryUtils;
3130
import org.springframework.beans.factory.FactoryBean;
3231
import org.springframework.beans.factory.InitializingBean;
3332
import org.springframework.beans.factory.ListableBeanFactory;
@@ -36,8 +35,8 @@
3635

3736
/**
3837
* A {@link FactoryBean} implementation that takes an interface which must have one or more
39-
* methods with the signatures <code>MyType xxx()</code> or <code>MyType xxx(MyIdType id)</code>
40-
* (typically, <code>MyService getService()</code> or <code>MyService getService(String id)</code>)
38+
* methods with the signatures {@code MyType xxx()} or {@code MyType xxx(MyIdType id)}
39+
* (typically, {@code MyService getService()} or {@code MyService getService(String id)})
4140
* and creates a dynamic proxy which implements that interface, delegating to an
4241
* underlying {@link org.springframework.beans.factory.BeanFactory}.
4342
*
@@ -51,7 +50,7 @@
5150
* setter or constructor injection of the target bean is preferable.</b>
5251
*
5352
* <p>On invocation of the no-arg factory method, or the single-arg factory
54-
* method with a String id of <code>null</code> or empty String, if exactly
53+
* method with a String id of {@code null} or empty String, if exactly
5554
* <b>one</b> bean in the factory matches the return type of the factory
5655
* method, that bean is returned, otherwise a
5756
* {@link org.springframework.beans.factory.NoSuchBeanDefinitionException}
@@ -64,7 +63,7 @@
6463
*
6564
* <p>A factory method argument will usually be a String, but can also be an
6665
* int or a custom enumeration type, for example, stringified via
67-
* <code>toString</code>. The resulting String can be used as bean name as-is,
66+
* {@code toString}. The resulting String can be used as bean name as-is,
6867
* provided that corresponding beans are defined in the bean factory.
6968
* Alternatively, {@link #setServiceMappings(java.util.Properties) a custom mapping}
7069
* between service ids and bean names can be defined.
@@ -99,7 +98,7 @@
9998
*
10099
*&lt;/beans></pre>
101100
*
102-
* <p>The attendant <code>MyClientBean</code> class implementation might then
101+
* <p>The attendant {@code MyClientBean} class implementation might then
103102
* look something like this:
104103
*
105104
* <pre class="code">package a.b.c;
@@ -151,7 +150,7 @@
151150
*
152151
*&lt;/beans></pre>
153152
*
154-
* <p>The attendant <code>MyClientBean</code> class implementation might then
153+
* <p>The attendant {@code MyClientBean} class implementation might then
155154
* look something like this:
156155
*
157156
* <pre class="code">package a.b.c;
@@ -202,8 +201,8 @@ public class ServiceLocatorFactoryBean implements FactoryBean<Object>, BeanFacto
202201

203202
/**
204203
* Set the service locator interface to use, which must have one or more methods with
205-
* the signatures <code>MyType xxx()</code> or <code>MyType xxx(MyIdType id)</code>
206-
* (typically, <code>MyService getService()</code> or <code>MyService getService(String id)</code>).
204+
* the signatures {@code MyType xxx()} or {@code MyType xxx(MyIdType id)}
205+
* (typically, {@code MyService getService()} or {@code MyService getService(String id)}).
207206
* See the {@link ServiceLocatorFactoryBean class-level Javadoc} for
208207
* information on the semantics of such methods.
209208
*/
@@ -214,8 +213,8 @@ public void setServiceLocatorInterface(Class interfaceType) {
214213
/**
215214
* Set the exception class that the service locator should throw if service
216215
* lookup failed. The specified exception class must have a constructor
217-
* with one of the following parameter types: <code>(String, Throwable)</code>
218-
* or <code>(Throwable)</code> or <code>(String)</code>.
216+
* with one of the following parameter types: {@code (String, Throwable)}
217+
* or {@code (Throwable)} or {@code (String)}.
219218
* <p>If not specified, subclasses of Spring's BeansException will be thrown,
220219
* for example NoSuchBeanDefinitionException. As those are unchecked, the
221220
* caller does not need to handle them, so it might be acceptable that
@@ -236,7 +235,7 @@ public void setServiceLocatorExceptionClass(Class serviceLocatorExceptionClass)
236235
* Set mappings between service ids (passed into the service locator)
237236
* and bean names (in the bean factory). Service ids that are not defined
238237
* here will be treated as bean names as-is.
239-
* <p>The empty string as service id key defines the mapping for <code>null</code> and
238+
* <p>The empty string as service id key defines the mapping for {@code null} and
240239
* empty string, and for factory methods without parameter. If not defined,
241240
* a single matching bean will be retrieved from the bean factory.
242241
* @param serviceMappings mappings between service ids and bean names,
@@ -271,8 +270,8 @@ public void afterPropertiesSet() {
271270
* Determine the constructor to use for the given service locator exception
272271
* class. Only called in case of a custom service locator exception.
273272
* <p>The default implementation looks for a constructor with one of the
274-
* following parameter types: <code>(String, Throwable)</code>
275-
* or <code>(Throwable)</code> or <code>(String)</code>.
273+
* following parameter types: {@code (String, Throwable)}
274+
* or {@code (Throwable)} or {@code (String)}.
276275
* @param exceptionClass the exception class
277276
* @return the constructor to use
278277
* @see #setServiceLocatorExceptionClass
@@ -364,12 +363,12 @@ private Object invokeServiceLocatorMethod(Method method, Object[] args) throws E
364363
try {
365364
String beanName = tryGetBeanName(args);
366365
if (StringUtils.hasLength(beanName)) {
367-
// Service locator for a specific bean name.
366+
// Service locator for a specific bean name
368367
return beanFactory.getBean(beanName, serviceLocatorMethodReturnType);
369368
}
370369
else {
371-
// Service locator for a bean type.
372-
return BeanFactoryUtils.beanOfTypeIncludingAncestors(beanFactory, serviceLocatorMethodReturnType);
370+
// Service locator for a bean type
371+
return beanFactory.getBean(serviceLocatorMethodReturnType);
373372
}
374373
}
375374
catch (BeansException ex) {

org.springframework.orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -76,12 +76,14 @@ public abstract class EntityManagerFactoryUtils {
7676
* Find an EntityManagerFactory with the given name in the given
7777
* Spring application context (represented as ListableBeanFactory).
7878
* <p>The specified unit name will be matched against the configured
79-
* peristence unit, provided that a discovered EntityManagerFactory
79+
* persistence unit, provided that a discovered EntityManagerFactory
8080
* implements the {@link EntityManagerFactoryInfo} interface. If not,
8181
* the persistence unit name will be matched against the Spring bean name,
8282
* assuming that the EntityManagerFactory bean names follow that convention.
83+
* <p>If no unit name has been given, this method will search for a default
84+
* EntityManagerFactory through {@link ListableBeanFactory#getBean(Class)}.
8385
* @param beanFactory the ListableBeanFactory to search
84-
* @param unitName the name of the persistence unit (may be <code>null</code> or empty,
86+
* @param unitName the name of the persistence unit (may be {@code null} or empty,
8587
* in which case a single bean of type EntityManagerFactory will be searched for)
8688
* @return the EntityManagerFactory
8789
* @throws NoSuchBeanDefinitionException if there is no such EntityManagerFactory in the context
@@ -108,17 +110,18 @@ public static EntityManagerFactory findEntityManagerFactory(
108110
return beanFactory.getBean(unitName, EntityManagerFactory.class);
109111
}
110112
else {
111-
return BeanFactoryUtils.beanOfType(beanFactory, EntityManagerFactory.class);
113+
// Find unique EntityManagerFactory bean in the context, falling back to parent contexts.
114+
return beanFactory.getBean(EntityManagerFactory.class);
112115
}
113116
}
114117

115118
/**
116119
* Obtain a JPA EntityManager from the given factory. Is aware of a
117120
* corresponding EntityManager bound to the current thread,
118121
* for example when using JpaTransactionManager.
119-
* <p>Note: Will return <code>null</code> if no thread-bound EntityManager found!
122+
* <p>Note: Will return {@code null} if no thread-bound EntityManager found!
120123
* @param emf EntityManagerFactory to create the EntityManager with
121-
* @return the EntityManager, or <code>null</code> if none found
124+
* @return the EntityManager, or {@code null} if none found
122125
* @throws DataAccessResourceFailureException if the EntityManager couldn't be obtained
123126
* @see JpaTransactionManager
124127
*/
@@ -132,11 +135,11 @@ public static EntityManager getTransactionalEntityManager(EntityManagerFactory e
132135
* Obtain a JPA EntityManager from the given factory. Is aware of a
133136
* corresponding EntityManager bound to the current thread,
134137
* for example when using JpaTransactionManager.
135-
* <p>Note: Will return <code>null</code> if no thread-bound EntityManager found!
138+
* <p>Note: Will return {@code null} if no thread-bound EntityManager found!
136139
* @param emf EntityManagerFactory to create the EntityManager with
137-
* @param properties the properties to be passed into the <code>createEntityManager</code>
138-
* call (may be <code>null</code>)
139-
* @return the EntityManager, or <code>null</code> if none found
140+
* @param properties the properties to be passed into the {@code createEntityManager}
141+
* call (may be {@code null})
142+
* @return the EntityManager, or {@code null} if none found
140143
* @throws DataAccessResourceFailureException if the EntityManager couldn't be obtained
141144
* @see JpaTransactionManager
142145
*/
@@ -154,11 +157,11 @@ public static EntityManager getTransactionalEntityManager(EntityManagerFactory e
154157
* Obtain a JPA EntityManager from the given factory. Is aware of a
155158
* corresponding EntityManager bound to the current thread,
156159
* for example when using JpaTransactionManager.
157-
* <p>Same as <code>getEntityManager</code>, but throwing the original PersistenceException.
160+
* <p>Same as {@code getEntityManager}, but throwing the original PersistenceException.
158161
* @param emf EntityManagerFactory to create the EntityManager with
159-
* @param properties the properties to be passed into the <code>createEntityManager</code>
160-
* call (may be <code>null</code>)
161-
* @return the EntityManager, or <code>null</code> if none found
162+
* @param properties the properties to be passed into the {@code createEntityManager}
163+
* call (may be {@code null})
164+
* @return the EntityManager, or {@code null} if none found
162165
* @throws javax.persistence.PersistenceException if the EntityManager couldn't be created
163166
* @see #getTransactionalEntityManager(javax.persistence.EntityManagerFactory)
164167
* @see JpaTransactionManager
@@ -273,15 +276,15 @@ public static void applyTransactionTimeout(Query query, EntityManagerFactory emf
273276

274277
/**
275278
* Convert the given runtime exception to an appropriate exception from the
276-
* <code>org.springframework.dao</code> hierarchy.
279+
* {@code org.springframework.dao} hierarchy.
277280
* Return null if no translation is appropriate: any other exception may
278281
* have resulted from user code, and should not be translated.
279282
* <p>The most important cases like object not found or optimistic locking failure
280283
* are covered here. For more fine-granular conversion, JpaTransactionManager etc
281284
* support sophisticated translation of exceptions via a JpaDialect.
282285
* @param ex runtime exception that occurred
283286
* @return the corresponding DataAccessException instance,
284-
* or <code>null</code> if the exception should not be translated
287+
* or {@code null} if the exception should not be translated
285288
*/
286289
public static DataAccessException convertJpaAccessExceptionIfPossible(RuntimeException ex) {
287290
// Following the JPA specification, a persistence provider can also
@@ -317,17 +320,17 @@ public static DataAccessException convertJpaAccessExceptionIfPossible(RuntimeExc
317320
if (ex instanceof PersistenceException) {
318321
return new JpaSystemException((PersistenceException) ex);
319322
}
320-
323+
321324
// If we get here, we have an exception that resulted from user code,
322325
// rather than the persistence provider, so we return null to indicate
323326
// that translation should not occur.
324-
return null;
327+
return null;
325328
}
326329

327330
/**
328331
* Close the given JPA EntityManager,
329332
* catching and logging any cleanup exceptions thrown.
330-
* @param em the JPA EntityManager to close (may be <code>null</code>)
333+
* @param em the JPA EntityManager to close (may be {@code null})
331334
* @see javax.persistence.EntityManager#close()
332335
*/
333336
public static void closeEntityManager(EntityManager em) {

org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,9 +24,7 @@
2424

2525
import org.springframework.beans.factory.BeanFactory;
2626
import org.springframework.beans.factory.BeanFactoryAware;
27-
import org.springframework.beans.factory.BeanFactoryUtils;
2827
import org.springframework.beans.factory.InitializingBean;
29-
import org.springframework.beans.factory.ListableBeanFactory;
3028
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
3129
import org.springframework.core.NamedThreadLocal;
3230
import org.springframework.transaction.NoTransactionException;
@@ -44,16 +42,16 @@
4442
*
4543
* <p>Subclasses are responsible for calling methods in this class in the correct order.
4644
*
47-
* <p>If no transaction name has been specified in the <code>TransactionAttribute</code>,
48-
* the exposed name will be the <code>fully-qualified class name + "." + method name</code>
45+
* <p>If no transaction name has been specified in the {@code TransactionAttribute},
46+
* the exposed name will be the {@code fully-qualified class name + "." + method name}
4947
* (by default).
5048
*
51-
* <p>Uses the <b>Strategy</b> design pattern. A <code>PlatformTransactionManager</code>
49+
* <p>Uses the <b>Strategy</b> design pattern. A {@code PlatformTransactionManager}
5250
* implementation will perform the actual transaction management, and a
53-
* <code>TransactionAttributeSource</code> is used for determining transaction definitions.
51+
* {@code TransactionAttributeSource} is used for determining transaction definitions.
5452
*
55-
* <p>A transaction aspect is serializable if its <code>PlatformTransactionManager</code>
56-
* and <code>TransactionAttributeSource</code> are serializable.
53+
* <p>A transaction aspect is serializable if its {@code PlatformTransactionManager}
54+
* and {@code TransactionAttributeSource} are serializable.
5755
*
5856
* @author Rod Johnson
5957
* @author Juergen Hoeller
@@ -68,7 +66,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
6866
// class for AspectJ aspects (which are not allowed to implement Serializable)!
6967

7068
/**
71-
* Holder to support the <code>currentTransactionStatus()</code> method,
69+
* Holder to support the {@code currentTransactionStatus()} method,
7270
* and to support communication between different cooperating advices
7371
* (e.g. before and after advice) if the aspect involves more than a
7472
* single method (as will be the case for around advice).
@@ -85,11 +83,11 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
8583
* An around advice such as an AOP Alliance MethodInterceptor can hold a
8684
* reference to the TransactionInfo throughout the aspect method.
8785
* <p>A TransactionInfo will be returned even if no transaction was created.
88-
* The <code>TransactionInfo.hasTransaction()</code> method can be used to query this.
86+
* The {@code TransactionInfo.hasTransaction()} method can be used to query this.
8987
* <p>To find out about specific transaction characteristics, consider using
90-
* TransactionSynchronizationManager's <code>isSynchronizationActive()</code>
91-
* and/or <code>isActualTransactionActive()</code> methods.
92-
* @return TransactionInfo bound to this thread, or <code>null</code> if none
88+
* TransactionSynchronizationManager's {@code isSynchronizationActive()}
89+
* and/or {@code isActualTransactionActive()} methods.
90+
* @return TransactionInfo bound to this thread, or {@code null} if none
9391
* @see TransactionInfo#hasTransaction()
9492
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isSynchronizationActive()
9593
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()
@@ -247,12 +245,8 @@ protected PlatformTransactionManager determineTransactionManager(TransactionAttr
247245
else if (this.transactionManagerBeanName != null) {
248246
return this.beanFactory.getBean(this.transactionManagerBeanName, PlatformTransactionManager.class);
249247
}
250-
else if (this.beanFactory instanceof ListableBeanFactory) {
251-
return BeanFactoryUtils.beanOfTypeIncludingAncestors(((ListableBeanFactory) this.beanFactory), PlatformTransactionManager.class);
252-
}
253248
else {
254-
throw new IllegalStateException(
255-
"Cannot retrieve PlatformTransactionManager beans from non-listable BeanFactory: " + this.beanFactory);
249+
return this.beanFactory.getBean(PlatformTransactionManager.class);
256250
}
257251
}
258252

@@ -262,7 +256,7 @@ else if (this.beanFactory instanceof ListableBeanFactory) {
262256
* @param method the method about to execute
263257
* @param targetClass the class that the method is being invoked on
264258
* @return a TransactionInfo object, whether or not a transaction was created.
265-
* The <code>hasTransaction()</code> method on TransactionInfo can be used to
259+
* The {@code hasTransaction()} method on TransactionInfo can be used to
266260
* tell if there was a transaction created.
267261
* @see #getTransactionAttributeSource()
268262
*/
@@ -307,14 +301,15 @@ protected String methodIdentification(Method method) {
307301
* Create a transaction if necessary based on the given TransactionAttribute.
308302
* <p>Allows callers to perform custom TransactionAttribute lookups through
309303
* the TransactionAttributeSource.
310-
* @param txAttr the TransactionAttribute (may be <code>null</code>)
304+
* @param txAttr the TransactionAttribute (may be {@code null})
311305
* @param joinpointIdentification the fully qualified method name
312306
* (used for monitoring and logging purposes)
313307
* @return a TransactionInfo object, whether or not a transaction was created.
314-
* The <code>hasTransaction()</code> method on TransactionInfo can be used to
308+
* The {@code hasTransaction()} method on TransactionInfo can be used to
315309
* tell if there was a transaction created.
316310
* @see #getTransactionAttributeSource()
317311
*/
312+
@SuppressWarnings("serial")
318313
protected TransactionInfo createTransactionIfNecessary(
319314
PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
320315

@@ -345,7 +340,7 @@ public String getName() {
345340

346341
/**
347342
* Prepare a TransactionInfo for the given attribute and status object.
348-
* @param txAttr the TransactionAttribute (may be <code>null</code>)
343+
* @param txAttr the TransactionAttribute (may be {@code null})
349344
* @param joinpointIdentification the fully qualified method name
350345
* (used for monitoring and logging purposes)
351346
* @param status the TransactionStatus for the current transaction
@@ -449,7 +444,7 @@ protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwabl
449444
/**
450445
* Reset the TransactionInfo ThreadLocal.
451446
* <p>Call this in all cases: exception or normal return!
452-
* @param txInfo information about the current transaction (may be <code>null</code>)
447+
* @param txInfo information about the current transaction (may be {@code null})
453448
*/
454449
protected void cleanupTransactionInfo(TransactionInfo txInfo) {
455450
if (txInfo != null) {

0 commit comments

Comments
 (0)