On revision 1 you scored 34/59 (58%). This time every option you clicked was recorded, so this page shows exactly what you picked and why it was wrong. Nothing here is guessed.
@PostConstruct visibility@PreDestroy,
"runs after DI" for a private @PostConstruct, "is called" for a protected @PreDestroy,
and you left "must be public" unticked in the constraints question. You also got the BPP phase, where AOP
proxies are made, the LTW agent, which modes change bytecode, the embedded server question and
@ModelAttribute right. Several of those were misses last time.
On the exact questions you'd seen before, you scored 19/25 (76%). On new questions testing the same facts, 15/34 (44%). Five times, you got a question right in its familiar wording and missed the same fact asked a different way:
| Fact | Familiar wording | New wording |
|---|---|---|
Non-web Environment sources | ✓ twice (retry 22, 24) | ✗ ticked servlet context params, twice |
@MockBean adds a bean if none exists | ✓ (retry 2) | ✗ left "adds one" out — 4th time |
What @ContextConfiguration loads | ✓ (retry 18) | ✗ "every auto-config in spring.factories" |
| Which classes are BFPPs | ✓ the Configurers (retry 3) | ✗ ticked the Configurers as BPPs |
| Excluding a class that's not on the classpath | ✓ excludeName (retry 21) | ✗ ticked exclude = Foo.class + scan filter |
So you're recognising questions, not yet applying the rule. The real exam rewords questions, so the 44% is the better guide. That's why this page is mostly new questions, and why the retry block comes last.
Each finished block is recorded in this browser. Reload to retake. Do blocks A–F first. Before you tick, say the rule to yourself (each section ends with one), then check every option against it.
| Drill block | Qs | Last | Best | Runs | Last done |
|---|---|---|---|---|---|
| Loading… | |||||
@Autowired attrs (1)
B · Environment: servlet params leaking into non-web — 4 misses
C · @ContextConfiguration as the auto-config door — 3 + @MockBean (1)
D · Final class vs final method — 3 misses
E · BPP vs BFPP, read the full name — 3 + lifecycle signatures (2)
F · Timeout property + excluding a missing class — 3 misses
Retry the 25, exact wording
| Question | You picked | Right answer |
|---|---|---|
| Plain Spring: which cycles start up? | field + setter + constructor | field + setter only |
Plain Spring: which throw BeanCurrentlyInCreationException? | setter + field | constructor + prototypes |
| Boot 2.7 field cycle fails. Fixes? | switch to constructor injection + refactor | refactor + @Lazy + allow-circular-references=true |
| Boot 2.6+ setter cycle, by default? | "resolves as in plain Spring" | startup fails |
@Lazy on a constructor parameter? | "nothing — only works on classes" | injects a lazy proxy, which breaks the cycle |
Where the belief probably comes from: "constructor injection is recommended" is true, and it's easy to slide from there to "constructor injection fixes cycles". It's the reverse. Constructor injection is recommended partly because it makes a cycle fail at startup, so you notice the design problem and fix it.
Walk through it. Two beans, A needs B and B needs A:
// CONSTRUCTOR cycle: A(B b), B(A a)
create A → call new A(?) → needs a B first
create B → call new B(?) → needs an A first
is there an A? No: new A(...) hasn't returned, so no A object exists
→ BeanCurrentlyInCreationException ✗ always
// SETTER / FIELD cycle: A has @Autowired B b; B has @Autowired A a
create A → new A() → A exists, fields empty
put an "early reference" to A in the singletonFactories cache
→ inject A.b → needs a B
create B → new B() → B exists
→ inject B.a → needs an A → found in the cache (the early reference)
B finished
A.b = B → A finished ✓ plain Spring
✗ Boot 2.6+ by default
The only question that matters: when the second bean asks for the first, has the first one's constructor finished? With setter/field injection, yes, so Spring can hand over an unfinished object. With a constructor, no, so there's nothing to hand over. Prototypes fail too, because Spring never caches unfinished prototypes.
| Plain Spring 5 | Boot 2.6+ default | Boot with spring.main.allow-circular-references=true | |
|---|---|---|---|
| Setter / field, singletons | Starts | Fails ("…form a cycle") | Starts |
| Constructor, singletons | Fails | Fails | Still fails — the property can't help |
| Prototypes | Fails | Fails | Fails |
@Lazy works on an injection point too, not only a class. Its targets
are type, method, constructor, parameter and field. On an injection point, Spring injects a proxy
straight away and only looks up the real bean when it's first used. Nothing waits for the other bean, so the
cycle is broken, even a constructor one.
@Autowired attributes (retry 11): you picked "required and
qualifier". If @Autowired had a qualifier attribute, you'd never write @Autowired
@Qualifier("x") as two annotations. The fact that it takes two annotations shows that
@Autowired only has required.
Environment 4 misses · 0/4 on the block| Question | You picked | Right answer |
|---|---|---|
Plain AnnotationConfigApplicationContext: sources? | env vars + system props + servlet context params | env vars + system props |
| Non-web app can read…? | all four, incl. web.xml context-param | env var, profiles, -D flag |
Which class adds jndiProperties? | "neither — JNDI isn't reachable" | StandardServletEnvironment |
| Web environment has…? | jndi + servletConfig + systemProperties (left out systemEnvironment) | all four |
A correction to revision 1: that page guessed you were giving JNDI to non-web apps. Your picks show the opposite. You never ticked JNDI for non-web. The leak is servlet context parameters, and on JNDI you went to "not reachable at all".
Picture what env.getPropertySources() would print:
// plain main(): new AnnotationConfigApplicationContext(AppConfig.class) → StandardEnvironment
[systemProperties, systemEnvironment]
// web app → StandardServletEnvironment = the same two, with three added in front
[servletConfigInitParams, servletContextInitParams, jndiProperties, systemProperties, systemEnvironment]
main() app has none, so
it has no web.xml and no context params.jndiProperties
(java:comp/env). Spring adds it when a JNDI context is available, which an app server
provides.systemEnvironment is
always there.Environment interface itself, so every app has them.@MockBean@ContextConfiguration to bring in auto-configuration| Question | You picked | Right answer |
|---|---|---|
What does @ContextConfiguration(classes = TestConfig.class) do? | "loads every auto-config in spring.factories" | loads TestConfig as plain config |
@DataJpaTest needs a library's auto-config | @ContextConfiguration(classes = …AutoConfiguration.class) | @ImportAutoConfiguration(…) |
@WebMvcTest needs FeignAutoConfiguration (retry 10) | same: @ContextConfiguration | @ImportAutoConfiguration(…) |
@MockBean: which are true? | registers a mock + field/class (left out "adds one if none exists") | all three |
Look at the names. Auto-configuration only comes in through an annotation with AutoConfiguration in its name, or one that contains it:
| Annotation | What it does | Brings in auto-config? |
|---|---|---|
@EnableAutoConfiguration | All auto-config candidates | Yes |
@SpringBootApplication | Includes @EnableAutoConfiguration | Yes |
@ImportAutoConfiguration(X.class) | Just the ones you name, as auto-config (ordering applied) | Yes |
@ContextConfiguration(classes = X.class) | spring-test's loader. The test's version of new AnnotationConfigApplicationContext(X.class) | No — X becomes plain config |
@ContextConfiguration predates Boot. It's in spring-test, which knows
nothing about spring.factories. So it can't load "every auto-config", and it isn't the way to add
one.
@MockBean, for the fourth time: the name ends in Bean, so it
puts a bean into the context. If a bean of that type exists, the mock replaces it. If none exists, it adds one.
Both are true.
@ContextConfiguration = plain classes you list. @MockBean = replace or add."| Question | You picked | Right answer |
|---|---|---|
final class Report, no interfaces, @Transactional | "created without a proxy; transactions silently skipped" | startup fails |
final class Billing, no interfaces (retry 14) | same: "silently skipped" | startup fails |
After a CGLIB proxy is made for OrderService | two objects + "target's bytecode has advice inserted" | two objects + OrderService.class unchanged |
| What's final | Can a proxy be made? | Result |
|---|---|---|
| The class, no interface | No — CGLIB can't extend it, JDK has no interface | Loud: startup fails, AopConfigException |
| The class, with an interface (JDK proxy) | Yes — JDK never extends | Works, through the interface |
| One method, class not final | Yes | Silent: the proxy can't override that method, so it goes straight to the target without advice |
"Silently skipped" needs a proxy to exist and let one method slip past it. A final class with no interface never gets a proxy, and Spring won't hand out an unadvised bean when advice was required. It stops.
Bytecode: CGLIB does generate new bytecode, but for a new subclass
(OrderService$$EnhancerBySpringCGLIB$$…). OrderService's own bytecode is untouched.
Advice inserted into the target's own bytecode is weaving.
| Question | You picked | Right answer |
|---|---|---|
| Which are BeanPostProcessors? | the two Configurers | Autowired… / CommonAnnotationBeanPostProcessor |
| Which hooks receive the bean instance? | after-init + postProcessBeanFactory | before-init + after-init |
| Order for one singleton | DI → constructor → BPP after-init | constructor → DI → BPP before → @PostConstruct → BPP after |
Which follow the @PostConstruct rules? | all four, including static | the three non-static ones |
| Which signatures are invalid? | returns String + static (left out init(ApplicationContext ctx)) | all three of those |
In the same session, the retry block asked "which are BFPPs?" and you picked the Configurers correctly. Then "which are BPPs?" got the same two. So the facts are there; you're mixing up the two acronyms while reading. Read the full names, not the acronyms. The answer is in the name:
postProcessBeanFactory(ConfigurableListableBeanFactory) receives the factory, not a
bean.…BeanPostProcessor classes are BPPs. …Configurer classes edit
definitions, so they're BFPPs.Lifecycle signatures. Visibility is fixed. The two you missed are the other rules:
@PostConstruct void init(ApplicationContext ctx) fails at startup. Spring
throws IllegalStateException: Lifecycle method annotation requires a no-arg method. You ticked "must
take no parameters" as a rule in the retry, but didn't apply it to a signature. Count the brackets.void name(), empty brackets, no static, any
visibility."server.tomcat.connection-timeout on either try| Question | You picked | Right answer |
|---|---|---|
| Which properties exist in Boot 2.5? | server.connection-timeout + server.timeout | server.tomcat.connection-timeout + server.jetty.connection-idle-timeout |
| Tomcat connection timeout (retry 17) | spring.tomcat.timeout | server.tomcat.connection-timeout |
| Exclude a class whose jar is missing | exclude = Foo.class + @ComponentScan filter | excludeName = "…" + spring.autoconfigure.exclude |
Build the property name from two rules:
server., never spring.
(server.port, server.servlet.context-path, server.ssl.*).server.tomcat.connection-timeout, server.jetty.connection-idle-timeout.
The old generic server.connection-timeout was removed in 2.3.Excluding a missing class: anything that takes a class literal
(exclude = Foo.class, classes = Foo.class) won't compile when Foo's jar
isn't there. So only the string forms work: excludeName = "com.acme.Foo" and
spring.autoconfigure.exclude=com.acme.Foo. Scan filters never apply to auto-config at all.
These are the 25 questions you missed on revision 1, reshuffled. Do them last. Because the wording is familiar, a high score here proves less than a high score on blocks A–F.
Environment) are at full marks a day later, those facts have stuck. Or say "build the Spring
Core clinic". Five of the six groups on this page are Core.