实测 Bean 生命周期的 15 个创建回调的顺序:BPP.beforeInstantiation → 构造器 → populate → 各种 Aware → BPP.before → @PostConstruct → afterPropertiesSet → initMethod → BPP.after;销毁顺序 @PreDestroy → destroy() → destroyMethod;prototype 关闭容器时 0 个销毁回调;@Bean 默认推断 close();初始化失败的 Bean 不会调用 @PreDestroy。
实测容器的两个扩展点:BeanPostProcessor 能把 Bean 换成 JDK 代理(按具体类注入就失败);多个 BPP 按 PriorityOrdered、Ordered、无顺序三组执行;被提前创建的 Bean(Early 构造器依赖 Service)不会被后注册的 BPP 处理,Spring 会打 WARN;BFPP 的 @Bean 方法非 static 时,配置类里的 @Autowired 字段是 null。
实测依赖注入的写法与候选解析:构造器、setter、字段三种方式 new 出来的差别;两个候选时 NoUniqueBeanDefinitionException,参数名、@Qualifier、@Primary、@Priority 各自能解决;两个 @Primary 仍冲突;@Order 只影响 List 的顺序;没有候选时单个依赖失败、List 是空的;泛型参数参与匹配。
实测循环依赖:setter 循环能解开但 B 初始化时看到的 A 是半成品;构造器循环抛 BeanCurrentlyInCreationException;SpringApplication 默认禁止循环引用;自定义 BPP 包装让 SA、SB 各被构造了 2 次;Spring AOP 的循环会提前暴露代理;@Lazy 可以打破构造器循环。
实测作用域:单例里直接注入 prototype 只在创建时注入一次(id 恒为 1);ObjectProvider、@Lookup 每次拿新对象;prototype 加 scoped proxy 是每次方法调用换一个对象;thread 作用域加 scoped proxy 才是按线程稳定;单例里的 int 字段 8 线程各 200000 次 n++ 丢了 100 万次以上。
实测 @Configuration 的 full 模式与 lite 模式:@Bean 方法互相调用时 full 模式只构造 1 次 A、lite 模式构造 3 次;static @Bean 不被拦截;改用方法参数注入最安全;300 个配置类把 proxyBeanMethods 设成 false,refresh 从 847 ms 降到 475 ms、少加载 1174 个类。
实测组件扫描:3000 个 @Component 的 scan() 是 220 ms,但扫描时新加载的类始终是 205 个(类到实例化时才加载);包里每多一个没有注解的普通类也要被读(8000 个比 0 个多花约 357 ms,401 减 44 算出的);主类放在默认包会扫描整个 classpath 导致启动失败;同名 @Component 抛 ConflictingBeanDefinitionException。
实测 @Profile 与 @Conditional:没有激活 profile 时默认是 default,一旦激活别的 default 就失效;"dev & !cloud" 这样的表达式可用;“registry 里没有才注册”的条件依赖配置类顺序(User 先 [dataSource],Fallback 先 [dataSource, fallbackDs]);类级别条件在 PARSE_CONFIGURATION 阶段求值,看不到 @Bean 的定义;类上的条件会一次跳过 @Import 和嵌套配置类。
实测 Environment 与 PropertySource:系统属性 > 环境变量 > @PropertySource 文件,addFirst 赢、addLast 同名键输;MY_NAME 环境变量可以用 my.name 取;没有 PropertySourcesPlaceholderConfigurer 时缺失的 @Value 会被原样注入字面量;yes/on/1 都被转成 true;@PropertySource 读中文 .properties 默认乱码。
实测 FactoryBean 与 ObjectProvider:FactoryBean 的产品在第一次 getBean 才创建,"&名字" 取到工厂本体;isSingleton 为 false 时每次 getBean 都新建;SmartFactoryBean 的产品容器不缓存(源码里有注释);getObjectType 返回 null 就按类型找不到;ObjectProvider 在没有、一个、两个候选时 getIfAvailable / getIfUnique 的结果不同,orderedStream 按 @Order 排序,它只推迟 prototype 的创建,不推迟 singleton。
实测 Spring 事件机制:默认同步,监听器在发布者线程里依次执行,一个失败后面的跳过且异常传回发布者;多播器配线程池后发布者 0 ms 返回、异常交给 ErrorHandler;泛型事件要实现 ResolvableTypeProvider 才按泛型匹配;在 @PostConstruct 里发布的事件会被 @EventListener 方法错过,ApplicationListener 的 Bean 却能收到。
实测 SpEL:@Value("#{...}") 的引用 Bean、安全导航、静态方法调用、集合投影与过滤;null 上取属性抛 EL1007E;StandardEvaluationContext 能调 Runtime 的静态方法,SimpleEvaluationContext 拒绝;每次重新解析表达式约 1300 ns,复用解析结果约 96 ns,编译模式约 5 到 7 ns。