← TikTok Interview Insights

TikTok·Software Engineer·Technical Phone Screen·Senior

SeniorPrefer not to say
May 2026Remote

Summary

Technical screen at TikTok for a software engineer role, pretty deep dive into Spring internals. Not the kind of interview where you can get by with surface-level answers.

Questions Asked (7)

Q1

Walk me through the full bean lifecycle in Spring, from creation through post-processing, initialization, and eventual destruction.

System DesignTechnical Trade-offs
Author's notes

I knew the broad strokes but fumbled the ordering of BeanPostProcessor hooks relative to InitializingBean.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Structure your answer as a chronological walkthrough of the bean lifecycle, starting from bean definition loading and ending with destruction. Highlight key extension points like BeanPostProcessor and BeanFactoryPostProcessor, and explain how they enable customization. Emphasize practical implications such as proxy creation for AOP and common pitfalls.

Pro tip: Mention that most beans in modern Spring are singletons and that the lifecycle is managed per bean definition, but prototype beans have a truncated lifecycle (no destruction callback). This shows depth and awareness of real-world usage.

1. Bean Definition and Instantiation

Explain how Spring reads bean definitions from configuration (XML, annotations, Java config) and registers them in the BeanFactory. Then describe instantiation via constructor or factory method, noting that this is where the bean object is created but not yet initialized.

2. Populate Properties and Dependency Injection

Describe how Spring injects dependencies (setter, field, constructor) and resolves circular dependencies. Mention that this step populates bean properties and ensures all required dependencies are available.

3. BeanPostProcessor Before Initialization

Explain that BeanPostProcessors are invoked before any initialization callbacks. This is where Spring applies custom logic like @Autowired processing, @PostConstruct handling, and AOP proxy creation.

4. Initialization Callbacks

Detail the initialization phase: afterPropertiesSet() from InitializingBean, custom init-method, and @PostConstruct. Clarify the order: @PostConstruct -> afterPropertiesSet -> init-method.

5. BeanPostProcessor After Initialization and Destruction

Explain that BeanPostProcessors are invoked after initialization, often wrapping the bean in a proxy. Then describe destruction: @PreDestroy, DisposableBean.destroy(), and custom destroy-method, noting that destruction only applies to singleton beans.

Key Points to Mention

  • BeanFactoryPostProcessor vs BeanPostProcessor: BeanFactoryPostProcessor modifies bean definitions before instantiation, while BeanPostProcessor modifies bean instances after instantiation.
  • Aware interfaces (e.g., BeanNameAware, ApplicationContextAware) are called during initialization, before BeanPostProcessor's postProcessBeforeInitialization.
  • Order of initialization: @PostConstruct, InitializingBean.afterPropertiesSet(), custom init-method.
  • Order of destruction: @PreDestroy, DisposableBean.destroy(), custom destroy-method.
  • Prototype beans do not have destruction callbacks; Spring does not manage their full lifecycle after creation.
  • AOP proxies are typically created by BeanPostProcessor (e.g., AbstractAutoProxyCreator) in postProcessAfterInitialization.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

What's the difference between JDK dynamic proxies and CGLIB proxies, and when does Spring choose one over the other?

Technical Trade-offsSystem Design
Author's notes

This one I actually felt okay about.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining both proxy mechanisms and their core differences (interface-based vs. subclass-based). Then explain Spring's decision criteria, emphasizing that Spring uses JDK proxies when the target implements interfaces and CGLIB otherwise, but also mention configuration options and trade-offs. Conclude with practical implications for performance and design.

Pro tip: Mention that Spring Boot 2.x defaults to CGLIB proxies (via spring.aop.proxy-target-class=true) to avoid interface requirements, but be ready to discuss why JDK proxies are still preferred in some cases (e.g., when interfaces are stable).

1. Define JDK Dynamic Proxies

Explain that JDK proxies are built into the JDK and create proxies only for interfaces. They use reflection and require the target to implement at least one interface.

2. Define CGLIB Proxies

Explain that CGLIB generates a subclass of the target class at runtime, so it can proxy classes without interfaces. It cannot proxy final classes or methods.

3. Compare Key Differences

Highlight differences: interface requirement, performance (CGLIB is generally faster after warm-up but slower to create), and limitations (final methods, constructors).

4. Explain Spring's Selection Logic

Describe that Spring uses JDK proxies if the target implements interfaces (unless proxyTargetClass=true), otherwise CGLIB. Mention that Spring Boot 2.x defaults to CGLIB.

5. Discuss Trade-offs and Best Practices

Talk about when to prefer one over the other: JDK proxies for interface-based design, CGLIB for legacy classes or when no interface exists. Mention performance considerations and Spring's configuration options.

Key Points to Mention

  • JDK proxies require interfaces; CGLIB proxies work by subclassing.
  • Spring's default behavior: JDK if interfaces are present, CGLIB otherwise.
  • Spring Boot 2.x defaults to CGLIB proxies (proxyTargetClass=true).
  • CGLIB cannot proxy final classes or methods; JDK proxies cannot proxy classes without interfaces.
  • Performance: CGLIB creation is slower but invocation can be faster; JDK proxies are simpler and part of the JDK.
  • Configuration: @EnableAspectJAutoProxy(proxyTargetClass=true) or spring.aop.proxy-target-class=true to force CGLIB.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How does Spring implement transaction management using proxies under the hood?

System DesignTechnical Trade-offs
Author's notes

Talked through the proxy intercepting the method call, opening a transaction, and committing or rolling back based on the outcome.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining that Spring uses AOP proxies to wrap beans with transactional behavior, then describe the two proxy types (JDK dynamic proxies and CGLIB) and how they intercept method calls to manage transactions. Finally, discuss the transaction interceptor and the underlying PlatformTransactionManager to show the full flow.

Pro tip: Mention the self-invocation problem and how it breaks proxy-based transaction management, then suggest solutions like AspectJ mode or self-injection to demonstrate deep practical knowledge.

1. Explain the role of AOP proxies

Describe how Spring AOP creates a proxy around beans annotated with @Transactional, intercepting method calls to apply transaction advice.

2. Differentiate proxy types

Explain that Spring uses JDK dynamic proxies for interface-based beans and CGLIB for class-based proxies, and when each is chosen.

3. Detail the interception mechanism

Describe how the proxy delegates to a TransactionInterceptor, which uses a PlatformTransactionManager to begin, commit, or rollback transactions based on method execution.

4. Discuss transaction propagation and attributes

Mention how propagation behavior (e.g., REQUIRED, REQUIRES_NEW) and other attributes are handled by the transaction manager during interception.

5. Address limitations and workarounds

Highlight the self-invocation issue where internal method calls bypass the proxy, and suggest solutions like AspectJ mode or self-injection.

Key Points to Mention

  • Spring AOP proxies (JDK dynamic proxies vs. CGLIB)
  • TransactionInterceptor and PlatformTransactionManager
  • Proxy creation only for beans with @Transactional or XML configuration
  • Transaction propagation and isolation levels
  • Self-invocation problem and its impact
  • AspectJ mode as an alternative for fine-grained control

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

How does Spring process annotations like @Transactional or @Autowired at runtime?

System DesignAPI & Integrations
Author's notes

Mentioned reflection and BeanPostProcessors doing most of the work during context startup.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining that Spring uses annotation processing at startup, primarily through BeanPostProcessors and reflection, to handle annotations like @Autowired and @Transactional. Then, differentiate between the two: @Autowired is processed by AutowiredAnnotationBeanPostProcessor for dependency injection, while @Transactional is handled by infrastructure proxies (e.g., via @EnableTransactionManagement) that wrap beans with transactional advice. Conclude by mentioning how this enables declarative programming and the role of the ApplicationContext.

Pro tip: Emphasize that @Transactional works via AOP proxies, so self-invocation (calling a @Transactional method from within the same class) bypasses the proxy and loses transactionality—a common pitfall in production. Mentioning this shows deep practical understanding.

1. Annotation Processing at Startup

Explain that Spring scans for annotations during application context initialization using classpath scanning and metadata readers. This is when bean definitions are created and annotations are detected.

2. @Autowired: Dependency Injection

Describe how AutowiredAnnotationBeanPostProcessor processes @Autowired by resolving dependencies from the context and injecting them via reflection (field, setter, or constructor injection).

3. @Transactional: Proxy-based AOP

Explain that @Transactional is handled by a BeanPostProcessor that wraps the bean in a proxy (JDK dynamic or CGLIB). The proxy intercepts method calls and applies transaction management advice.

4. Role of BeanPostProcessors

Highlight that BeanPostProcessors are the key extension points: they modify bean instances after initialization, enabling both injection and proxying for annotations.

5. Runtime Behavior and Pitfalls

Summarize how these mechanisms enable declarative features at runtime, and mention common pitfalls like self-invocation bypassing proxies or circular dependencies with @Autowired.

Key Points to Mention

  • BeanPostProcessors (e.g., AutowiredAnnotationBeanPostProcessor, InfrastructureAdvisorAutoProxyCreator)
  • Reflection for dependency injection and proxy creation
  • AOP proxies (JDK dynamic proxies vs. CGLIB) for @Transactional
  • ApplicationContext and bean lifecycle (instantiation, population, initialization)
  • Transaction management infrastructure (@EnableTransactionManagement, PlatformTransactionManager)
  • Self-invocation issue with @Transactional and how to avoid it (e.g., injecting self or using AspectJ)

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

Explain how classpath scanning works and how Spring discovers and registers beans.

System DesignTechnical Trade-offs
Author's notes

Shorter exchange on this one.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining classpath scanning as the process of discovering components on the classpath, then walk through Spring's scanning mechanism from configuration to bean registration. Emphasize how this supports Spring's dependency injection and auto-configuration, and discuss trade-offs like startup time and flexibility.

Pro tip: Mention that classpath scanning is a double-edged sword: it simplifies configuration but can slow startup and hide dependencies; showing awareness of this trade-off demonstrates senior-level thinking.

1. Define Classpath Scanning

Explain that classpath scanning is a technique where Spring searches the classpath for classes annotated with stereotypes like @Component, @Service, @Repository, and @Controller.

2. Triggering the Scan

Describe how scanning is triggered via @ComponentScan or XML <context:component-scan>, specifying base packages to search.

3. Scanning Process

Detail how Spring uses ASM to read bytecode metadata without loading classes, identifies candidate components, and applies filters like include/exclude patterns.

4. Bean Registration

Explain that for each candidate, Spring creates a BeanDefinition and registers it with the BeanFactory, later instantiating and wiring beans.

5. Trade-offs and Best Practices

Discuss performance implications (startup time, memory) and recommend explicit configuration or narrowing scan scope for large applications.

Key Points to Mention

  • Stereotype annotations: @Component, @Service, @Repository, @Controller
  • @ComponentScan and its attributes (basePackages, includeFilters, excludeFilters)
  • ASM bytecode reading for metadata without class loading
  • BeanDefinition registration and BeanFactoryPostProcessor role
  • Interaction with auto-configuration and conditional beans
  • Trade-offs: startup performance, explicit vs. implicit configuration

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

What are the different bean scopes in Spring and what are the practical implications of each?

System DesignTechnical Trade-offs
Author's notes

Singleton, prototype, request, session.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by listing the core Spring bean scopes (singleton, prototype, request, session, application, websocket) and briefly define each. Then focus on the practical implications—such as state management, memory footprint, thread safety, and performance—and relate them to real-world scenarios like web applications and microservices. Conclude with trade-offs and best practices for choosing the right scope.

Pro tip: Emphasize that singleton beans must be stateless to avoid concurrency issues, and mention that prototype beans are often used for stateful objects but require careful lifecycle management since Spring does not manage their destruction. This shows you understand the nuances beyond just definitions.

1. List and define the scopes

Enumerate the standard Spring bean scopes: singleton, prototype, request, session, application, and websocket. Provide a one-sentence definition for each.

2. Explain singleton and prototype implications

Discuss how singleton scope is the default, creates one instance per container, and requires statelessness for thread safety. For prototype, highlight that a new instance is created per request, leading to higher memory usage and the need for manual cleanup.

3. Cover web-specific scopes

Describe request, session, application, and websocket scopes, which are only valid in web-aware contexts. Explain how they map to HTTP request, user session, ServletContext, and WebSocket lifecycle respectively.

4. Discuss practical trade-offs

Compare scopes in terms of memory footprint, performance, thread safety, and lifecycle management. Give examples of when to use each, such as using prototype for stateful helpers and request scope for per-request data.

5. Summarize best practices

Conclude with recommendations: prefer singleton for stateless services, use prototype sparingly, and leverage web scopes for web-specific state. Mention that scopes can be combined with proxies to inject shorter-lived beans into longer-lived ones.

Key Points to Mention

  • Singleton is the default scope and creates one shared instance per Spring container; it must be stateless to avoid concurrency issues.
  • Prototype scope creates a new bean instance each time it is requested, which can lead to increased memory usage and requires manual destruction handling.
  • Request, session, application, and websocket scopes are only available in web-aware Spring ApplicationContexts and tie bean lifecycle to HTTP request, user session, ServletContext, or WebSocket session respectively.
  • Scoped proxies (e.g., @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)) allow injecting request- or session-scoped beans into singleton beans.
  • Choosing the wrong scope can cause memory leaks, thread safety issues, or unexpected behavior; e.g., using singleton for stateful beans leads to data corruption.
  • In microservices, singleton is common for stateless services, while prototype might be used for stateful components like builders or validators.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q7

How does Spring detect and handle circular dependencies between beans?

System DesignAlgorithms & Data Structures
Author's notes

This is where I got the most turned around.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Explain Spring's three-level cache mechanism and how it resolves circular dependencies for singleton beans via early exposure of references. Then discuss the limitations (e.g., constructor injection, prototype beans) and how Spring handles or fails to handle them. Finally, mention best practices to avoid circular dependencies.

Pro tip: Emphasize that circular dependencies are a design smell and that Spring's support is a fallback, not a feature to rely on. Mention that constructor injection circular dependencies fail fast, which is actually beneficial for catching design issues early.

1. Define circular dependency

Briefly explain what a circular dependency is: two or more beans that reference each other directly or indirectly, forming a cycle.

2. Explain Spring's resolution for singletons

Describe the three-level cache: singletonObjects (fully initialized), earlySingletonObjects (early references), and singletonFactories (ObjectFactory). Explain how Spring exposes early references to break the cycle.

3. Discuss limitations and failures

Cover cases where Spring cannot resolve circular dependencies: constructor injection (throws BeanCurrentlyInCreationException), prototype-scoped beans, and @Async proxies. Mention that Spring Boot 2.6+ disables circular references by default.

4. Provide solutions and best practices

Suggest using setter/field injection, @Lazy annotation, or redesigning to eliminate the cycle. Emphasize that avoiding circular dependencies is the best approach.

Key Points to Mention

  • Three-level cache: singletonObjects, earlySingletonObjects, singletonFactories
  • Early reference exposure via ObjectFactory
  • Constructor injection circular dependencies fail with BeanCurrentlyInCreationException
  • Prototype-scoped beans cannot resolve circular dependencies
  • Spring Boot 2.6+ disables circular references by default (spring.main.allow-circular-references=false)
  • @Lazy annotation as a workaround to break cycles

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.