Skip to content

Commit defc246

Browse files
committed
Fail early FactoryBean instantiation for LinkageError
Closes gh-26425
1 parent a991c23 commit defc246

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -1022,6 +1022,11 @@ private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, Root
10221022
throw ex;
10231023
}
10241024
catch (BeanCreationException ex) {
1025+
// Don't swallow a linkage error since it contains a full stacktrace on
1026+
// first occurrence... and just a plain NoClassDefFoundError afterwards.
1027+
if (ex.contains(LinkageError.class)) {
1028+
throw ex;
1029+
}
10251030
// Instantiation failure, maybe too early...
10261031
if (logger.isDebugEnabled()) {
10271032
logger.debug("Bean creation exception on singleton FactoryBean type check: " + ex);

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

+69-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -16,14 +16,23 @@
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+
import static org.assertj.core.api.Assertions.fail;
32+
2533
/**
2634
* @author Andy Wilkinson
35+
* @author Liu Dongmiao
2736
*/
2837
public class AggressiveFactoryBeanInstantiationTests {
2938

@@ -49,17 +58,66 @@ public void beanMethodFactoryBean() {
4958
}
5059
}
5160

61+
@Test
62+
public void checkLinkageError() {
63+
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
64+
context.register(BeanMethodConfigurationWithExceptionInInitializer.class);
65+
context.refresh();
66+
fail("Should have thrown BeanCreationException");
67+
}
68+
catch (BeanCreationException ex) {
69+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
70+
PrintWriter pw = new PrintWriter(baos);
71+
ex.printStackTrace(pw);
72+
pw.flush();
73+
String stackTrace = baos.toString();
74+
assertThat(stackTrace.contains(".<clinit>")).isTrue();
75+
assertThat(stackTrace.contains("java.lang.NoClassDefFoundError")).isFalse();
76+
}
77+
}
78+
5279

5380
@Configuration
5481
static class BeanMethodConfiguration {
5582

5683
@Bean
84+
public String foo() {
85+
return "foo";
86+
}
87+
88+
@Bean
89+
public AutowiredBean autowiredBean() {
90+
return new AutowiredBean();
91+
}
92+
93+
@Bean
94+
@DependsOn("autowiredBean")
5795
public SimpleFactoryBean simpleFactoryBean(ApplicationContext applicationContext) {
5896
return new SimpleFactoryBean(applicationContext);
5997
}
6098
}
6199

62100

101+
@Configuration
102+
static class BeanMethodConfigurationWithExceptionInInitializer extends BeanMethodConfiguration {
103+
104+
@Bean
105+
@DependsOn("autowiredBean")
106+
@Override
107+
public SimpleFactoryBean simpleFactoryBean(ApplicationContext applicationContext) {
108+
new ExceptionInInitializer();
109+
return new SimpleFactoryBean(applicationContext);
110+
}
111+
}
112+
113+
114+
static class AutowiredBean {
115+
116+
@Autowired
117+
String foo;
118+
}
119+
120+
63121
static class SimpleFactoryBean implements FactoryBean<Object> {
64122

65123
public SimpleFactoryBean(ApplicationContext applicationContext) {
@@ -76,4 +134,14 @@ public Class<?> getObjectType() {
76134
}
77135
}
78136

137+
138+
static class ExceptionInInitializer {
139+
140+
private static final int ERROR = callInClinit();
141+
142+
private static int callInClinit() {
143+
throw new UnsupportedOperationException();
144+
}
145+
}
146+
79147
}

0 commit comments

Comments
 (0)