#!/usr/bin/env bash # Two facts about the circular-reference machinery, read out of the Framework and Boot jars rather than from docs: # 36 the defaults of spring.main.allow-circular-references and spring.main.lazy-initialization # 37 which post-processors supply an early reference, and the exception handler in preInstantiateSingleton set -euo pipefail cd "$(dirname "$0")/.." mkdir -p output M2=~/.m2/repository/org/springframework BOOT=$M2/boot/spring-boot/4.1.1/spring-boot-4.1.1.jar AOP=$M2/spring-aop/7.0.9/spring-aop-7.0.9.jar CTX=$M2/spring-context/7.0.9/spring-context-7.0.9.jar BEANS=$M2/spring-beans/7.0.9/spring-beans-7.0.9.jar JP() { javap "$@" 2>&1 | grep -v '^Picked up'; } { echo "# Defaults read from spring-configuration-metadata.json in spring-boot-4.1.1.jar" echo unzip -p "$BOOT" META-INF/spring-configuration-metadata.json | python3 -c ' import json,sys d=json.load(sys.stdin) for p in d["properties"]: if p["name"] in ("spring.main.allow-circular-references","spring.main.lazy-initialization"): print("%-40s default=%s" % (p["name"], p.get("defaultValue"))) ' } > output/36-main-property-defaults.txt { echo "# Who hands out an early reference, and the handler in preInstantiateSingleton (Spring Framework 7.0.9 jars)" echo echo "--- the class that draws the report, in spring-boot-4.1.1.jar ---" unzip -l "$BOOT" | awk '/BeanCurrentlyInCreationFailureAnalyzer/ {print $4}' echo echo "--- AbstractAutoProxyCreator (spring-aop): declared methods that mention 'early' ---" JP -p -cp "$AOP" org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator | grep -i early | sed 's/^ *//' echo echo "--- AbstractAdvisingBeanPostProcessor (spring-aop): declared members that mention 'early' ---" n=$(JP -p -cp "$AOP" org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor | grep -ci early || true) echo "matches: $n" echo echo "--- the @Async post-processor's ancestry ---" JP -cp "$CTX:$AOP" org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor | grep -o 'class [^ ]* extends [^ ]*' JP -cp "$AOP" org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor | grep -o 'class [^ ]* extends [^ ]*' echo echo "--- DefaultListableBeanFactory.preInstantiateSingleton(String, RootBeanDefinition): exception table ---" JP -p -c -cp "$BEANS" org.springframework.beans.factory.support.DefaultListableBeanFactory \ | awk '/private java.util.concurrent.CompletableFuture<\?> preInstantiateSingleton\(/ {f=1} f&&/Exception table:/ {t=1} t {print} t&&/^ private void instantiateSingletonInBackgroundThread/ {exit}' \ | grep -v 'instantiateSingletonInBackgroundThread' | sed 's/^ *//' } > output/37-early-reference-bytecode.txt cat output/36-main-property-defaults.txt output/37-early-reference-bytecode.txt