spring version: 6.2.10
two circular reference:
@Component
@Order(1)
public class TestA {
@Autowired
private TestB testB;
private String name;
// get and set
public String hello () {
return "hello A" + this.getName();
}
public String otherName () {
return testB.getName();
}
}
@Component
@Order(1)
public class TestB {
@Autowired
private TestA testA;
private String name;
// get and set
public String hello () {
return "hello B" + this.getName();
}
public String otherName () {
return testA.getName();
}
}
postprocessor:
@Component
public class BugPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (TestA.class.isAssignableFrom(bean.getClass())) {
System.out.println("Modifying TestA bean before initialization");
return new TestA(); // use another object to replace it
}
if (TestB.class.isAssignableFrom(bean.getClass())) {
System.out.println("Modifying TestB bean before initialization");
return new TestB(); // use another object to replace it
}
return bean; // return original bean
}
}
AOP:
@Aspect
@Component
public class AOPConfig {
@Pointcut("execution(* com.voidvvv.issue.service.*.*(..))" )
public void pointCut() {}
@Before("pointCut()")
public void before() {
System.out.println("AOP before");
}
}
controller
@RestController
@Lazy
@RequestMapping("/test")
public class TestController {
@Autowired
private TestA testA;
@Autowired
private TestB testB;
@GetMapping("/show")
public String show() {
StringBuilder sb = new StringBuilder();
sb.append("show TestA: " + testA.hello() + "\t\n");
sb.append(System.lineSeparator());
sb.append("show TestB: " + testB.hello() + "\t");
sb.append(System.lineSeparator());
sb.append("show TestB in TestA: " + testA.otherName() + "\t");
sb.append(System.lineSeparator());
sb.append("show TestA in TestB: " + testB.otherName() + "\t");
sb.append(System.lineSeparator());
return sb.toString();
}
}
confiuration:
spring.main.allow-circular-references=true
exception: we can successfully start up the application. then we request : http://localhost:8080/test/show, we will get a NPE in TestA, the TestB object in TestA is null.
exceptation: we need get an error when we start up the application since we have illegal beans in our application.
minimal demo: https://github.com/voidvvv/spring_bean_issue
I use springboot 3.5.5 in this demo to represent this issue.
Comment From: voidvvv
the root cause analysis is in the minimal demo.