diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 7dfa6ab56a3..d8447022b14 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * 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. @@ -1013,6 +1013,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac throw ex; } catch (BeanCreationException ex) { + // Don't swallow a linkage error since it contains a full stacktrace on + // first occurrence... and just a plain NoClassDefFoundError afterwards. + if (ex.contains(LinkageError.class)) { + throw ex; + } // Instantiation failure, maybe too early... if (logger.isDebugEnabled()) { logger.debug("Bean creation exception on singleton FactoryBean type check: " + ex); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/AggressiveFactoryBeanInstantiationTests.java b/spring-context/src/test/java/org/springframework/context/annotation/AggressiveFactoryBeanInstantiationTests.java index 9bec2460979..5f97cd7f5c9 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/AggressiveFactoryBeanInstantiationTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/AggressiveFactoryBeanInstantiationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * 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. @@ -16,14 +16,23 @@ package org.springframework.context.annotation; +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; + import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + /** * @author Andy Wilkinson + * @author Liu Dongmiao */ public class AggressiveFactoryBeanInstantiationTests { @@ -49,17 +58,66 @@ public class AggressiveFactoryBeanInstantiationTests { } } + @Test + public void checkLinkageError() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) { + context.register(BeanMethodConfigurationWithExceptionInInitializer.class); + context.refresh(); + fail("Should have thrown BeanCreationException"); + } + catch (BeanCreationException ex) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintWriter pw = new PrintWriter(baos); + ex.printStackTrace(pw); + pw.flush(); + String stackTrace = baos.toString(); + assertThat(stackTrace.contains(".")).isTrue(); + assertThat(stackTrace.contains("java.lang.NoClassDefFoundError")).isFalse(); + } + } + @Configuration static class BeanMethodConfiguration { @Bean + public String foo() { + return "foo"; + } + + @Bean + public AutowiredBean autowiredBean() { + return new AutowiredBean(); + } + + @Bean + @DependsOn("autowiredBean") public SimpleFactoryBean simpleFactoryBean(ApplicationContext applicationContext) { return new SimpleFactoryBean(applicationContext); } } + @Configuration + static class BeanMethodConfigurationWithExceptionInInitializer extends BeanMethodConfiguration { + + @Bean + @DependsOn("autowiredBean") + @Override + public SimpleFactoryBean simpleFactoryBean(ApplicationContext applicationContext) { + new ExceptionInInitializer(); + return new SimpleFactoryBean(applicationContext); + } + } + + + static class AutowiredBean { + + @Autowired + String foo; + } + + static class SimpleFactoryBean implements FactoryBean { public SimpleFactoryBean(ApplicationContext applicationContext) { @@ -76,4 +134,14 @@ public class AggressiveFactoryBeanInstantiationTests { } } + + static class ExceptionInInitializer { + + private static final int ERROR = callInClinit(); + + private static int callInClinit() { + throw new UnsupportedOperationException(); + } + } + }