Skip to content

Commit

Permalink
Fail early FactoryBean instantiation for LinkageError
Browse files Browse the repository at this point in the history
  • Loading branch information
jhoeller authored and lxbzmy committed Mar 26, 2022
1 parent 7bcd474 commit 274afcb
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -1022,6 +1022,11 @@ private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, Root
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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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 {

Expand All @@ -49,17 +58,66 @@ public void beanMethodFactoryBean() {
}
}

@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(".<clinit>")).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<Object> {

public SimpleFactoryBean(ApplicationContext applicationContext) {
Expand All @@ -76,4 +134,14 @@ public Class<?> getObjectType() {
}
}


static class ExceptionInInitializer {

private static final int ERROR = callInClinit();

private static int callInClinit() {
throw new UnsupportedOperationException();
}
}

}

0 comments on commit 274afcb

Please sign in to comment.