Skip to content

Commit 4e54c25

Browse files
committed
Fail early FactoryBean instantiation for LinkageError
In 0288878 to resolve gh-22409, a little bug was introduced: if there is LinkageError in FactoryBean instantiation, no first exception. In JVM, if a class cannot be initialized, it acts like this: - at the first time, it will show the real reason and stack - then, only show "NoClassDefFoundError: Could not initialize class xxx"
1 parent 584dabb commit 4e54c25

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

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

+8
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,14 @@ private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, Root
10221022
throw ex;
10231023
}
10241024
catch (BeanCreationException ex) {
1025+
// LinkageError is unresolvable
1026+
Throwable cause = ex.getCause();
1027+
while (cause != null) {
1028+
if (cause instanceof LinkageError) {
1029+
throw ex;
1030+
}
1031+
cause = cause.getCause();
1032+
}
10251033
// Instantiation failure, maybe too early...
10261034
if (logger.isDebugEnabled()) {
10271035
logger.debug("Bean creation exception on singleton FactoryBean type check: " + ex);

spring-context/src/test/java/org/springframework/context/annotation/AggressiveFactoryBeanInstantiationTests.java

+64
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,19 @@
1616

1717
package org.springframework.context.annotation;
1818

19+
import java.io.ByteArrayOutputStream;
20+
import java.io.PrintWriter;
21+
1922
import org.junit.jupiter.api.Test;
2023

24+
import org.springframework.beans.factory.BeanCreationException;
2125
import org.springframework.beans.factory.BeanFactoryUtils;
2226
import org.springframework.beans.factory.FactoryBean;
27+
import org.springframework.beans.factory.annotation.Autowired;
2328
import org.springframework.context.ApplicationContext;
2429

30+
import static org.assertj.core.api.Assertions.assertThat;
31+
2532
/**
2633
* @author Andy Wilkinson
2734
*/
@@ -49,6 +56,23 @@ public void beanMethodFactoryBean() {
4956
}
5057
}
5158

59+
@Test
60+
public void beanMethodFactoryBeanWithError() {
61+
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
62+
context.register(BeanMethodConfigurationWithError.class, StringTypeConfiguration.class);
63+
try {
64+
context.refresh();
65+
} catch (BeanCreationException ex) {
66+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
67+
PrintWriter pw = new PrintWriter(baos);
68+
ex.printStackTrace(pw);
69+
pw.flush();
70+
String stackTrace = baos.toString();
71+
assertThat(stackTrace.contains(SimpleLinkageErrorClass.class.getSimpleName() + ".<clinit>")).isTrue();
72+
}
73+
}
74+
}
75+
5276

5377
@Configuration
5478
static class BeanMethodConfiguration {
@@ -60,6 +84,33 @@ public SimpleFactoryBean simpleFactoryBean(ApplicationContext applicationContext
6084
}
6185

6286

87+
@Configuration
88+
static class BeanMethodConfigurationWithError {
89+
90+
@Bean
91+
public SimpleFactoryBean simpleFactoryBean(ApplicationContext applicationContext) {
92+
SimpleFactoryBean simpleFactoryBean = new SimpleFactoryBean(applicationContext);
93+
// cause a linkage error
94+
new SimpleLinkageErrorClass();
95+
return simpleFactoryBean;
96+
}
97+
}
98+
99+
100+
@Configuration
101+
static class StringTypeConfiguration {
102+
103+
@Autowired
104+
private String foo;
105+
106+
@Bean
107+
public String foo() {
108+
return "foo";
109+
}
110+
111+
}
112+
113+
63114
static class SimpleFactoryBean implements FactoryBean<Object> {
64115

65116
public SimpleFactoryBean(ApplicationContext applicationContext) {
@@ -76,4 +127,17 @@ public Class<?> getObjectType() {
76127
}
77128
}
78129

130+
131+
static class SimpleLinkageErrorClass {
132+
133+
private static final int ERROR = checkError();
134+
135+
public SimpleLinkageErrorClass() {
136+
}
137+
138+
private static int checkError() {
139+
throw new NoSuchMethodError();
140+
}
141+
}
142+
79143
}

0 commit comments

Comments
 (0)