These interview questions were collected from every corner of the internet
Talk about the underlying implementation of Spring IOC Reflection The value of the factory Design patterns A few key methods createBeanFactory getBean doGetBean createBean doCreateBean createBeanInstance(getDeclaredConstructor, newInstance) populateBean flowchart TD A[Start] --> B["createBeanFactory()create DefaultListableBeanFactory"] B --> C[Load BeanDefinitionsparse XML/annotations] C --> D["getBean(beanName)external call entry"] D --> E["doGetBean(beanName)"] E --> F{Get singleton from cache?} F -->|Yes| G[Return the cached Bean] F -->|No| H["createBean(beanName, mbd)"] H --> I["doCreateBean(beanName, mbd)"] I --> J["createBeanInstance()getDeclaredConstructor + newInstance"] J --> K["populateBean()property filling / dependency injection"] K --> L["initializeBean()initialization callbacks"] L --> M[Register destroy methods] M --> N[Return the complete Bean instance] Talk about your understanding of Spring IOC — its principle and implementation The IOC idea DI as the means of implementation What is a container, what is a Bean BeanDefinition Where it’s read from XML Annotations Where it’s stored All BeanDefinitions are stored in a Map inside DefaultListableBeanFactory The container lifecycle flowchart TD START([🚀 Program starts]) --> REFRESH["AbstractApplicationContext.refresh()"] REFRESH --> PHASE1 subgraph PHASE1["🔵 Phase 1: Preparation"] direction TB A1["prepareRefresh()\nrecord start time\nset container state to 'active'\ninitialize environment variables"] --> A2 A2["obtainFreshBeanFactory()\ncreate DefaultListableBeanFactory\nthe container's core repository"] --> A3 A3["prepareBeanFactory()\nregister basic BeanPostProcessors\nregister Aware-related processors\nregister the default environment Bean"] end PHASE1 --> PHASE2 subgraph PHASE2["🟢 Phase 2: Load BeanDefinitions (read the blueprints)"] direction TB B1["scan the packages specified by @ComponentScan\nor read the XML config file"] --> B2 B2["parse annotations / XML\nrecognize @Component @Service\n@Repository @Controller @Bean"] --> B3 B3["generate a BeanDefinition for each Bean\nrecord: class name, scope, lazy or not\ninit method, destroy method, dependencies"] --> B4 B4[("store into beanDefinitionMap\nkey = beanName\nvalue = BeanDefinition")] end PHASE2 --> PHASE3 subgraph PHASE3["🟡 Phase 3: Modify BeanDefinitions (edit the blueprints)"] direction TB C1["invokeBeanFactoryPostProcessors()\nrun all BeanFactoryPostProcessors"] --> C2 C2["ConfigurationClassPostProcessor\nhandle @Configuration @Import\n@PropertySource @ComponentScan\n👉 Spring Boot auto-configuration triggers here"] --> C3 C3["PropertySourcesPlaceholderConfigurer\nreplace all ${xxx} placeholders in\nBeanDefinitions with real values"] --> C4 C4[/"all BeanDefinitions finalized\nthe blueprints no longer change"/] end PHASE3 --> PHASE4 subgraph PHASE4["🌸 Phase 4: Register BeanPostProcessors (workers take their posts)"] direction TB D1["registerBeanPostProcessors()\nregister by priority\nPriorityOrdered → Ordered → ordinary"] --> D2 D2["AutowiredAnnotationBeanPostProcessor\nhandles @Autowired @Value"] --> D3 D3["CommonAnnotationBeanPostProcessor\nhandles @PostConstruct @PreDestroy @Resource"] --> D4 D4["AnnotationAwareAspectJAutoProxyCreator\ndetects aspects, generates AOP proxies"] --> D5 D5[/"all workers in place\nwaiting to intervene during Bean creation\nnot working yet"/] end PHASE4 --> PHASE5 subgraph PHASE5["🟣 Phase 5: Initialize container infrastructure"] direction TB E1["initMessageSource()\ninitialize i18n resources"] --> E2 E2["initApplicationEventMulticaster()\ninitialize the event multicaster"] --> E3 E3["onRefresh()\n⭐ Spring Boot starts here\nTomcat / Jetty / Undertow\nthe web container begins listening on a port"] --> E4 E4["registerListeners()\nregister all ApplicationListeners\nlisten for container events"] end PHASE5 --> PHASE6 subgraph PHASE6["🟠 Phase 6: Instantiate all singleton Beans"] direction TB F1["finishBeanFactoryInitialization()\npreInstantiateSingletons()\niterate all non-lazy singleton BeanDefinitions"] --> F2 F2["execute getBean() one by one\ntrigger each Bean's lifecycle\ninstantiate → fill properties → Aware callbacks\n→ pre-processing → init method → post-processing"] --> F3 F3[("all singleton Beans stored in\nthe singletonObjects level-1 cache\n✅ all ready")] end PHASE6 --> PHASE7 subgraph PHASE7["✅ Phase 7: Container ready"] direction TB G1["finishRefresh()\nclean up resources used at startup\ninitialize the lifecycle processor"] --> G2 G2["publish ContextRefreshedEvent\nnotify all listeners: container startup complete"] --> G3 G3[/"container enters running state\ncan handle business requests"/] end G3 --> RUNNING([🎉 Container running normally]) RUNNING -.->|"receive shutdown signal\nCtrl+C / kill / close()"| PHASE8 subgraph PHASE8["🔴 Phase 8: Container destruction"] direction TB H1["publish ContextClosedEvent\nnotify all listeners: container about to close"] --> H2 H2["stop the web container\nTomcat stops accepting new requests"] --> H3 H3["run all Beans' destroy logic\n@PreDestroy → destroy() → destroy-method\ndestroy in reverse registration order"] --> H4 H4["clear all caches\nsingletonObjects cleared\nbeanDefinitionMap cleared"] --> H5 H5["set container state to 'closed'\nactive = false / closed = true"] end H5 --> END([💀 Container destruction complete]) style START fill:#43A047,color:#fff style RUNNING fill:#43A047,color:#fff style END fill:#e53935,color:#fff style REFRESH fill:#1E88E5,color:#fff The Bean lifecycle flowchart TD START([🌱 Start creating the Bean]) --> A A["① Instantiation\nInstantiation\nreflectively call the constructor\nnew an empty shell object\nall fields are null at this point"] --> B B["② Put into the level-3 cache\nsingletonFactories\nexpose the half-built object early\nto prepare for circular dependencies"] --> C C["③ Property filling\npopulateBean()\nhandle @Autowired @Value\ninject the dependent Beans"] --> D subgraph AWARE["④ Aware callbacks"] direction TB D["BeanNameAware\ntell the Bean its own name"] --> E E["BeanFactoryAware\npass the BeanFactory to the Bean"] --> F F["ApplicationContextAware\npass the ApplicationContext to the Bean"] end subgraph INIT["⑤ Initialization initializeBean()"] direction TB G["pre-processing\npostProcessBeforeInitialization()\nall BeanPostProcessors run one by one\n📌 @PostConstruct is called here"] --> INITMETHOD subgraph INITMETHOD["init methods (executed in order)"] direction TB H1["1st: @PostConstruct\n(already run in pre-processing)"] --> H2 H2["2nd: afterPropertiesSet()\nimplement the InitializingBean interface"] --> H3 H3["3rd: init-method\n@Bean(initMethod='xxx') or XML config"] end INITMETHOD --> I I["post-processing\npostProcessAfterInitialization()\nall BeanPostProcessors run one by one\n⭐ AOP proxies are generated here"] end AWARE --> INIT I --> J subgraph CACHE["⑥ Store into the cache"] direction TB J["remove from the level-3 cache singletonFactories\nremove from the level-2 cache earlySingletonObjects"] --> K K["store into the level-1 cache singletonObjects\n✅ complete Bean ready"] end K --> READY([🎉 Bean is now usable]) READY -.->|"container closes"| DESTROY subgraph DESTROY["⑦ Destruction phase (on container close)"] direction TB D1["1st: @PreDestroy\nmethod is called"] --> D2 D2["2nd: destroy()\nimplement the DisposableBean interface"] --> D3 D3["3rd: destroy-method\n@Bean(destroyMethod='xxx') or XML config"] end D3 --> END([💀 Bean destruction complete]) Spring’s three-level cache dependency flow sequenceDiagram participant Spring as Spring container participant L3 as Level-3 cachesingletonFactories participant L2 as Level-2 cacheearlySingletonObjects participant L1 as Level-1 cachesingletonObjects Note over Spring: Start creating A Spring->>Spring: ① new A empty-shell object Spring->>L3: ② store A's ObjectFactory lambda Note over Spring: Injecting properties into A, discovers it needs B Spring->>Spring: ③ new B empty-shell object Spring->>L3: ④ store B's ObjectFactory lambda Note over Spring: Injecting properties into B, discovers it needs A Spring->>L1: ⑤ getBean(A), check level-1 cache L1-->>Spring: ❌ not there Spring->>L2: check level-2 cache L2-->>Spring: ❌ not there Spring->>L3: check level-3 cache L3-->>Spring: ✅ found A's lambda! Spring->>Spring: ⑥ execute the lambda(generate proxy A if a proxy is needed) Spring->>L2: ⑦ put the early reference into the level-2 cache Spring->>L3: remove A from the level-3 cache Note over Spring: B gets A's early reference, B finishes initialization Spring->>L1: ⑧ put B into the level-1 cache ✅ Spring->>L3: remove B from the level-3 cache Note over Spring: Back in A's flow, B is ready, A finishes initialization Spring->>L1: ⑨ put A into the level-1 cache ✅ Spring->>L2: remove A from the level-2 cache Note over L1: Finally: the level-1 cache holds complete A and B ✅ Case Level-3 cache lambda executed Level-2 cache No circular dep, no AOP stored the lambda ❌ not executed not used No circular dep, with AOP stored the lambda ❌ not executed not used Circular dep, no AOP stored the lambda ✅ executed stores the raw object Circular dep, with AOP stored the lambda ✅ executed stores the proxy object When Spring Bean caches are placed and removed When Spring Bean’s three-level caches are placed and removed Cache What it stores When placed When removed Level-3 singletonFactories The Bean’s factory lambda Right after instantiation When the factory is called (promoted to level-2) or when the Bean completes Level-2 earlySingletonObjects The early-exposed half-built Bean The moment the level-3 factory is called When the Bean is fully initialized and placed in level-1 Level-1 singletonObjects The complete, usable Bean After initialization fully completes When the container closes and destroys The difference between BeanFactory and FactoryBean What is a FactoryBean public interface FactoryBean<T> { // Return the Bean instance (can involve complex creation logic) T getObject() throws Exception; // Return the Bean's type Class<?> getObjectType(); // Whether it's a singleton default boolean isSingleton() { return true; } } Similarities Both are used to create Bean objects Differences Creating an object with BeanFactory must follow the strict lifecycle process, which is too complex. If you want to simply customize the creation of some object while still handing it to Spring to manage, you must implement the FactoryBean interface isSingleton — whether it’s a singleton getObjectType — get the returned object’s type getObject — customize the object-creation process Dimension BeanFactory FactoryBean Role Container/factory interface A special Bean Function Manages the lifecycle of all Beans Customizes the creation of a specific Bean Positioning Infrastructure (the IOC container) Business extension (creating complex objects) How it’s used Implemented and used by the Spring framework Implemented by the developer, registered into the container Common implementations DefaultListableBeanFactory SqlSessionFactoryBean, ProxyFactoryBean Who creates whom BeanFactory creates and manages FactoryBean FactoryBean creates business objects flowchart LR subgraph BeanFactory[BeanFactory - IOC container] direction LR Bean1[ordinary Bean] Bean2[ordinary Bean] FB[FactoryBeanspecial Bean] end FB -->|call getObject| Result[business object] User[developer] -->|getBean| BF[BeanFactory] BF -->|return| Bean1 BF -->|return| Bean2 BF -->|return getObject result| Result BF -->|add & prefix| FB Design patterns used in Spring Singleton Prototype (scope set to prototype) Factory BeanFactory Template Method JdbcTemplate TransactionTemplate RestTemplate RedisTemplate Strategy XmlBeanDefinitionReader PropertiesBeanDefinitionReader Observer listener event multicast Adapter HandlerAdapter Decorator BeanWrapper Chain of Responsibility When using AOP, an interceptor chain is generated first The filter chain of Spring MVC Proxy Dynamic proxy Delegate delegate The underlying implementation principle of Spring AOP 🥇 Level 1: characterize it in one sentence (opening) “The underlying essence of Spring AOP is dynamic proxy. When the container initializes a Bean, Spring intercepts via the BeanPostProcessor mechanism, decides whether the Bean needs enhancement, and if so, uses a dynamic proxy to generate a proxy object that replaces the original Bean when registered into the container. All subsequent calls to this Bean actually go through the proxy object.”
...