Skip to content

Commit 3d2e4c3

Browse files
committed
Refined throwing of BeanCreationExceptions (and reflection exceptions)
Issue: SPR-14883
1 parent b42d731 commit 3d2e4c3

File tree

6 files changed

+52
-80
lines changed

6 files changed

+52
-80
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -243,23 +243,28 @@ public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final
243243

244244
// Let's check for lookup methods here..
245245
if (!this.lookupMethodsChecked.contains(beanName)) {
246-
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
247-
@Override
248-
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
249-
Lookup lookup = method.getAnnotation(Lookup.class);
250-
if (lookup != null) {
251-
LookupOverride override = new LookupOverride(method, lookup.value());
252-
try {
253-
RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
254-
mbd.getMethodOverrides().addOverride(override);
255-
}
256-
catch (NoSuchBeanDefinitionException ex) {
257-
throw new BeanCreationException(beanName,
258-
"Cannot apply @Lookup to beans without corresponding bean definition");
246+
try {
247+
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
248+
@Override
249+
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
250+
Lookup lookup = method.getAnnotation(Lookup.class);
251+
if (lookup != null) {
252+
LookupOverride override = new LookupOverride(method, lookup.value());
253+
try {
254+
RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
255+
mbd.getMethodOverrides().addOverride(override);
256+
}
257+
catch (NoSuchBeanDefinitionException ex) {
258+
throw new BeanCreationException(beanName,
259+
"Cannot apply @Lookup to beans without corresponding bean definition");
260+
}
259261
}
260262
}
261-
}
262-
});
263+
});
264+
}
265+
catch (IllegalStateException ex) {
266+
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
267+
}
263268
this.lookupMethodsChecked.add(beanName);
264269
}
265270

spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java

Lines changed: 2 additions & 3 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-2016 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.
@@ -103,7 +103,6 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
103103
* @see org.springframework.beans.MutablePropertyValues
104104
*/
105105
PropertyValues postProcessPropertyValues(
106-
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
107-
throws BeansException;
106+
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
108107

109108
}

spring-beans/src/main/java/org/springframework/beans/factory/config/Scope.java

Lines changed: 6 additions & 1 deletion
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-2016 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.
@@ -68,6 +68,7 @@ public interface Scope {
6868
* @param objectFactory the {@link ObjectFactory} to use to create the scoped
6969
* object if it is not present in the underlying storage mechanism
7070
* @return the desired object (never {@code null})
71+
* @throws IllegalStateException if the underlying scope is not currently active
7172
*/
7273
Object get(String name, ObjectFactory<?> objectFactory);
7374

@@ -84,6 +85,7 @@ public interface Scope {
8485
* removing an object.
8586
* @param name the name of the object to remove
8687
* @return the removed object, or {@code null} if no object was present
88+
* @throws IllegalStateException if the underlying scope is not currently active
8789
* @see #registerDestructionCallback
8890
*/
8991
Object remove(String name);
@@ -112,6 +114,7 @@ public interface Scope {
112114
* so it can safely be executed without an enclosing try-catch block.
113115
* Furthermore, the Runnable will usually be serializable, provided
114116
* that its target object is serializable as well.
117+
* @throws IllegalStateException if the underlying scope is not currently active
115118
* @see org.springframework.beans.factory.DisposableBean
116119
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getDestroyMethodName()
117120
* @see DestructionAwareBeanPostProcessor
@@ -123,6 +126,7 @@ public interface Scope {
123126
* E.g. the HttpServletRequest object for key "request".
124127
* @param key the contextual key
125128
* @return the corresponding object, or {@code null} if none found
129+
* @throws IllegalStateException if the underlying scope is not currently active
126130
*/
127131
Object resolveContextualObject(String key);
128132

@@ -139,6 +143,7 @@ public interface Scope {
139143
* underlying storage mechanism has no obvious candidate for such an ID.
140144
* @return the conversation ID, or {@code null} if there is no
141145
* conversation ID for the current scope
146+
* @throws IllegalStateException if the underlying scope is not currently active
142147
*/
143148
String getConversationId();
144149

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -479,21 +479,11 @@ protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] ar
479479
"BeanPostProcessor before instantiation of bean failed", ex);
480480
}
481481

482-
try {
483-
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
484-
if (logger.isDebugEnabled()) {
485-
logger.debug("Finished creating instance of bean '" + beanName + "'");
486-
}
487-
return beanInstance;
488-
}
489-
catch (BeanCreationException ex) {
490-
// A previously detected exception with proper bean creation context already...
491-
throw ex;
492-
}
493-
catch (Throwable ex) {
494-
throw new BeanCreationException(
495-
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
482+
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
483+
if (logger.isDebugEnabled()) {
484+
logger.debug("Finished creating instance of bean '" + beanName + "'");
496485
}
486+
return beanInstance;
497487
}
498488

499489
/**
@@ -532,7 +522,7 @@ protected Object doCreateBean(final String beanName, final RootBeanDefinition mb
532522
}
533523
catch (Throwable ex) {
534524
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
535-
"Post-processing failed of bean type [" + beanType + "] failed", ex);
525+
"Post-processing of merged bean definition failed", ex);
536526
}
537527
mbd.postProcessed = true;
538528
}
@@ -948,12 +938,9 @@ private FactoryBean<?> getNonSingletonFactoryBeanForTypeCheck(String beanName, R
948938
* @param mbd the merged bean definition for the bean
949939
* @param beanType the actual type of the managed bean instance
950940
* @param beanName the name of the bean
951-
* @throws BeansException if any post-processing failed
952941
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
953942
*/
954-
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
955-
throws BeansException {
956-
943+
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
957944
for (BeanPostProcessor bp : getBeanPostProcessors()) {
958945
if (bp instanceof MergedBeanDefinitionPostProcessor) {
959946
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
@@ -996,12 +983,9 @@ protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition
996983
* @param beanClass the class of the bean to be instantiated
997984
* @param beanName the name of the bean
998985
* @return the bean object to use instead of a default instance of the target bean, or {@code null}
999-
* @throws BeansException if any post-processing failed
1000986
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
1001987
*/
1002-
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
1003-
throws BeansException {
1004-
988+
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
1005989
for (BeanPostProcessor bp : getBeanPostProcessors()) {
1006990
if (bp instanceof InstantiationAwareBeanPostProcessor) {
1007991
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
214214
if (singletonObject == null) {
215215
if (this.singletonsCurrentlyInDestruction) {
216216
throw new BeanCreationNotAllowedException(beanName,
217-
"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
217+
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
218218
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
219219
}
220220
if (logger.isDebugEnabled()) {

spring-core/src/main/java/org/springframework/util/ReflectionUtils.java

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,6 @@ public static void makeAccessible(Constructor<?> ctor) {
483483
* @param clazz the class to introspect
484484
* @param mc the callback to invoke for each method
485485
* @since 4.2
486-
* @throws IllegalStateException if introspection fails
487486
* @see #doWithMethods
488487
*/
489488
public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
@@ -505,7 +504,6 @@ public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
505504
* twice, unless excluded by a {@link MethodFilter}.
506505
* @param clazz the class to introspect
507506
* @param mc the callback to invoke for each method
508-
* @throws IllegalStateException if introspection fails
509507
* @see #doWithMethods(Class, MethodCallback, MethodFilter)
510508
*/
511509
public static void doWithMethods(Class<?> clazz, MethodCallback mc) {
@@ -520,7 +518,6 @@ public static void doWithMethods(Class<?> clazz, MethodCallback mc) {
520518
* @param clazz the class to introspect
521519
* @param mc the callback to invoke for each method
522520
* @param mf the filter that determines the methods to apply the callback to
523-
* @throws IllegalStateException if introspection fails
524521
*/
525522
public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
526523
// Keep backing up the inheritance hierarchy.
@@ -550,7 +547,6 @@ else if (clazz.isInterface()) {
550547
* Get all declared methods on the leaf class and all superclasses.
551548
* Leaf class methods are included first.
552549
* @param leafClass the class to introspect
553-
* @throws IllegalStateException if introspection fails
554550
*/
555551
public static Method[] getAllDeclaredMethods(Class<?> leafClass) {
556552
final List<Method> methods = new ArrayList<Method>(32);
@@ -568,7 +564,6 @@ public void doWith(Method method) {
568564
* Leaf class methods are included first and while traversing the superclass hierarchy
569565
* any methods found with signatures matching a method already included are filtered out.
570566
* @param leafClass the class to introspect
571-
* @throws IllegalStateException if introspection fails
572567
*/
573568
public static Method[] getUniqueDeclaredMethods(Class<?> leafClass) {
574569
final List<Method> methods = new ArrayList<Method>(32);
@@ -609,33 +604,27 @@ public void doWith(Method method) {
609604
* interfaces, since those are effectively to be treated just like declared methods.
610605
* @param clazz the class to introspect
611606
* @return the cached array of methods
612-
* @throws IllegalStateException if introspection fails
613607
* @see Class#getDeclaredMethods()
614608
*/
615609
private static Method[] getDeclaredMethods(Class<?> clazz) {
610+
Assert.notNull(clazz, "Class must not be null");
616611
Method[] result = declaredMethodsCache.get(clazz);
617612
if (result == null) {
618-
try {
619-
Method[] declaredMethods = clazz.getDeclaredMethods();
620-
List<Method> defaultMethods = findConcreteMethodsOnInterfaces(clazz);
621-
if (defaultMethods != null) {
622-
result = new Method[declaredMethods.length + defaultMethods.size()];
623-
System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length);
624-
int index = declaredMethods.length;
625-
for (Method defaultMethod : defaultMethods) {
626-
result[index] = defaultMethod;
627-
index++;
628-
}
629-
}
630-
else {
631-
result = declaredMethods;
613+
Method[] declaredMethods = clazz.getDeclaredMethods();
614+
List<Method> defaultMethods = findConcreteMethodsOnInterfaces(clazz);
615+
if (defaultMethods != null) {
616+
result = new Method[declaredMethods.length + defaultMethods.size()];
617+
System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length);
618+
int index = declaredMethods.length;
619+
for (Method defaultMethod : defaultMethods) {
620+
result[index] = defaultMethod;
621+
index++;
632622
}
633-
declaredMethodsCache.put(clazz, (result.length == 0 ? NO_METHODS : result));
634623
}
635-
catch (Throwable ex) {
636-
throw new IllegalStateException("Failed to introspect Class [" + clazz +
637-
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
624+
else {
625+
result = declaredMethods;
638626
}
627+
declaredMethodsCache.put(clazz, (result.length == 0 ? NO_METHODS : result));
639628
}
640629
return result;
641630
}
@@ -661,7 +650,6 @@ private static List<Method> findConcreteMethodsOnInterfaces(Class<?> clazz) {
661650
* @param clazz the target class to analyze
662651
* @param fc the callback to invoke for each field
663652
* @since 4.2
664-
* @throws IllegalStateException if introspection fails
665653
* @see #doWithFields
666654
*/
667655
public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
@@ -680,7 +668,6 @@ public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
680668
* class hierarchy to get all declared fields.
681669
* @param clazz the target class to analyze
682670
* @param fc the callback to invoke for each field
683-
* @throws IllegalStateException if introspection fails
684671
*/
685672
public static void doWithFields(Class<?> clazz, FieldCallback fc) {
686673
doWithFields(clazz, fc, null);
@@ -692,7 +679,6 @@ public static void doWithFields(Class<?> clazz, FieldCallback fc) {
692679
* @param clazz the target class to analyze
693680
* @param fc the callback to invoke for each field
694681
* @param ff the filter that determines the fields to apply the callback to
695-
* @throws IllegalStateException if introspection fails
696682
*/
697683
public static void doWithFields(Class<?> clazz, FieldCallback fc, FieldFilter ff) {
698684
// Keep backing up the inheritance hierarchy.
@@ -720,20 +706,14 @@ public static void doWithFields(Class<?> clazz, FieldCallback fc, FieldFilter ff
720706
* in order to avoid the JVM's SecurityManager check and defensive array copying.
721707
* @param clazz the class to introspect
722708
* @return the cached array of fields
723-
* @throws IllegalStateException if introspection fails
724709
* @see Class#getDeclaredFields()
725710
*/
726711
private static Field[] getDeclaredFields(Class<?> clazz) {
712+
Assert.notNull(clazz, "Class must not be null");
727713
Field[] result = declaredFieldsCache.get(clazz);
728714
if (result == null) {
729-
try {
730-
result = clazz.getDeclaredFields();
731-
declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
732-
}
733-
catch (Throwable ex) {
734-
throw new IllegalStateException("Failed to introspect Class [" + clazz +
735-
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
736-
}
715+
result = clazz.getDeclaredFields();
716+
declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
737717
}
738718
return result;
739719
}
@@ -742,7 +722,6 @@ private static Field[] getDeclaredFields(Class<?> clazz) {
742722
* Given the source object and the destination, which must be the same class
743723
* or a subclass, copy all fields, including inherited fields. Designed to
744724
* work on objects with public no-arg constructors.
745-
* @throws IllegalStateException if introspection fails
746725
*/
747726
public static void shallowCopyFieldState(final Object src, final Object dest) {
748727
if (src == null) {

0 commit comments

Comments
 (0)