Revision 3 for Exam Drill #21 · 7 Oct 2026 · 19 misses · 30 new drills + 14 true/false + 19 retries

Revision 3 — new questions up from 44% to 62%. Now stop leaving true options out

On revision 2 you scored 43/62 (69%). The number that matters went up: on new questions you got 23/37 (62%), up from 15/34 (44%). This page goes through the 19 you missed, using exactly what you picked.

62%
New questions, up from 44%
4/6
Environment, up from 0/4
10 / 19
Misses where a true option was left out
4
Misses on @Lazy

What moved since revision 2

The two patterns behind most of the 19

1. Leaving out true options. In 10 of the 19, you left out an option that was true. In six of them you ticked nothing false, so the only mistake was stopping too soon:

QuestionTrue option you left out
Where can @Lazy go?On a @Component class
Which bring in auto-config?@ImportAutoConfiguration, which you picked correctly in two other questions
@MockBean (block C)Replaces an existing bean · separate cached contexts
@MockBean (retry)Field or class · adds one if none exists
Real Boot 2.5 propertiesserver.port
Boot 2.7 cycle fixes@Lazy

The fix is a technique, not more facts. On "select all", treat each option as a separate true/false question, and give each a yes or no before you click Check. The true-or-false block trains exactly that.

2. An old wrong answer coming back. In block A you correctly put @Lazy on a field and a constructor parameter. Then the retry showed the revision-1 wording, and you picked "nothing — @Lazy only works on classes", your revision-1 answer, again. Familiar wording brings back the answer you gave last time, not the rule. When an option feels familiar, check it against the rule anyway.

My drill progress on this page

Each finished block is recorded in this browser. Reload to retake. Order: blocks 1–6, then true or false, then the retry. On every "select all", give each option a yes or no before you click Check.

Drill blockQsLastBestRunsLast done
Loading…

The 19, in six groups

1 · @Lazy and which cycles start — 6 misses 2 · @MockBean and the auto-config annotations — 5 misses 3 · exclude vs excludeName, scan filters — 3 misses 4 · Which proxy problems are silent — 2 misses 5 · Web Environment adds, it doesn't replace — 2 misses 6 · What a BPP receives — 1 miss True or false: the options you keep ticking Retry the 19, exact wording

1 · @Lazy, and which cycles start 6 misses

Your picks

Constructor cycles are fixed. @Lazy and field cycles in plain Spring are left

QuestionYou pickedRight answer
Where can @Lazy go?parameter + field (left out class)class + field + parameter
@Lazy on a constructor parameter? (retry)"nothing — only works on classes" — same as revision 1injects a lazy proxy
Boot 2.7 field-cycle fixes (retry)refactor + property (left out @Lazy)refactor + property + @Lazy
Plain-Spring constructor cycle fixessetter + refactor + the Boot property (left out @Lazy)setter + refactor + @Lazy
Plain Spring, field-injection cycleBeanCurrentlyInCreationExceptionstarts
Which throw, plain Spring? (retry)constructor + field (left out prototypes)constructor + prototypes

@Lazy is in four of these, so learn it as one picture. It has two jobs, depending on where you put it:

@Lazy @Component class ReportService { … }           // on a CLASS (or @Bean method):
                                                     //   the bean itself is created on first use

class A {
    A(@Lazy B b) { … }                               // on an INJECTION POINT (parameter, field):
    @Autowired @Lazy C c;                            //   Spring injects a proxy now and looks up
}                                                    //   the real B / C on first call

The injection-point form is what breaks cycles. A gets a stand-in for B straight away, so A's constructor finishes without waiting for B. That works for any cycle, constructor ones included, in plain Spring and in Boot. It's the one fix that's always on the list. Compare the property: spring.main.allow-circular-references=true is Boot-only, and it only brings back the setter/field behaviour. It never rescues a constructor cycle.

The field-cycle misses: read "plain Spring" vs "Boot". In plain Spring, field injection behaves like setter injection, since both happen after the constructor. So a field cycle between singletons starts. It fails only in Boot 2.6+ (the default) and for prototypes. Before answering, underline which one the question says:

Plain SpringBoot 2.6+ defaultFixed by @Lazy?Fixed by the property?
Field / setter, singletonsStartsFailsYesYes (Boot)
Constructor, singletonsFailsFailsYesNo
PrototypesFailsFailsYesNo
Rule to say before ticking: "@Lazy goes anywhere (class, field, parameter) and always breaks a cycle. The property is Boot-only and setter/field-only. Plain Spring: field = setter = starts."

2 · @MockBean, and the annotations that bring in auto-config 5 misses

Your picks

@MockBean has three true facts. You keep picking one or two

QuestionYou pickedRight answer
@MockBean: which are true? (block C)only "adds a bean if none exists"+ replaces existing · + separate cached contexts
@MockBean: which are true? (retry)only "registers a mock in the context"+ field or class · + adds one if none
@DataJpaTest needs Acme's auto-config (retry)@MockBean AcmeClientAutoConfiguration@ImportAutoConfiguration(…)
Which bring in auto-config?Enable + SpringBootApplication (left out Import)all three
@ContextConfiguration(classes = AppConfig.class) is closest to…@ImportAutoConfiguration(AppConfig.class)new AnnotationConfigApplicationContext(AppConfig.class)

@MockBean as one picture. Every true statement about it comes from this:

@WebMvcTest(OrderController.class)
@MockBean(AuditLog.class)              // ① on the CLASS: a mock goes in the context, no field
class OrderControllerTest {
    @MockBean PaymentClient payments;  // ① on a FIELD: a mock goes in the context AND into this field
}

// ② what happens to the context, for each @MockBean type:
//     a PaymentClient bean already exists → the mock REPLACES it
//     no PaymentClient bean exists        → the mock is ADDED
// ③ the set of mocks is part of the context's cache key:
//     test classes with different @MockBean sets get separate contexts (slower suite)

If you can answer ① where it goes, ② replace and add, and ③ caching, you can't under-select. The only false one is "same as @Mock": @Mock never touches a Spring context.

Why @MockBean can't bring in auto-config: it would register a Mockito mock of the auto-config class. A mock is an empty stand-in, and Spring never reads its @Bean methods, so none of the beans Acme should provide would be created.

The annotations that bring in auto-config. All three have "AutoConfiguration" in the name, or contain an annotation that does:

AnnotationBrings in
@EnableAutoConfigurationevery auto-config whose conditions match
@SpringBootApplicationthe same, because it includes @EnableAutoConfiguration
@ImportAutoConfiguration(X.class)only the ones you name. Slice tests use it internally
@ContextConfiguration, @Import, @MockBeanno auto-config

"Closest to" @ContextConfiguration: both it and @ImportAutoConfiguration take classes, which is why they look alike. Ask what happens to the class you pass. @ContextConfiguration builds the test context from your classes, as plain config, just like new AnnotationConfigApplicationContext(AppConfig.class). In a Boot test it also replaces the usual search for your @SpringBootApplication, which is why it's wrong for adding one extra thing.

Rule to say before ticking: "@MockBean: field or class; replace or add; cached separately. Auto-config only enters through a name with AutoConfiguration in it."

3 · exclude vs excludeName, and scan filters 3 misses · the scan filter for the 3rd time

Your picks

"Missing class" is a condition in some questions, not all. And scan filters never work

QuestionYou pickedRight answer
Which can remove an auto-config class? (no mention of a missing class)property + excludeName + @ComponentScan filter (left out exclude)exclude + excludeName + property
Why does exclude = Foo.class fail when Foo's jar is missing?"it works — exclude and excludeName are the same"the class literal doesn't compile
Real Boot 2.5 propertiesthe two timeouts (left out server.port)server.port + both timeouts

Look at the two attributes' Java types:

public @interface SpringBootApplication {
    Class<?>[] exclude()   default {};   // exclude = Foo.class        ← needs Foo to compile
    String[]   excludeName() default {};   // excludeName = "com.acme.Foo" ← never needs Foo
}

They have the same effect when Foo is on the classpath. They're not the same when it isn't, because a .class literal is checked by the compiler. So "can it remove an auto-config?" gives exclude a yes, and "the jar is missing" gives it a no. Check which question you're answering.

@ComponentScan(excludeFilters) is wrong every time. This is the third time you've ticked it (exam Q56, revision 1, today). Scanning never finds auto-config classes in the first place. They're imported from a list (spring.factories) by AutoConfigurationImportSelector, so a scan filter has nothing to filter.

server.port: the timeout options made it feel like a timeout question, but the question was "which are real?". server.port is the best-known Boot property there is. Giving each option its own yes or no would have caught it.

Rule to say before ticking: "exclude = class (needs the jar), excludeName = string (doesn't). Both work when the class is there. Scan filters never remove auto-config."

4 · Only one proxy problem is loud 2 misses · swapped the other way this time

Your picks

Last time a final class was "silent". This time a final method "fails startup"

QuestionYou pickedRight answer
Which start fine, but the advice silently doesn't run?self-invocation + final class (left out private + final method)self-invocation + private + final method
CGLIB-proxied class, public final void issue()"startup fails"runs without a transaction

You got "final class → startup fails" right in both retries, then applied it to the final method as well. There's only one loud case, so learn that one and treat everything else as silent:

Is there a proxy?What you see
Final class, no interfaceNo — none can be builtLOUD: startup fails (AopConfigException)
Final methodYesSilent: the subclass can't override it, so the call passes straight through
Private methodYesSilent: can't be overridden
this.method()YesSilent: the call never goes through the proxy

The test is "is there a proxy?" If there is one, the app starts, and certain calls just slip past it. Startup only fails when Spring can't build a proxy at all.

Rule to say before ticking: "One loud case: final class with no interface. Final method, private method, self-call: all silent."

5 · A web Environment adds sources; it doesn't replace them 2 misses

Your picks

You got 4 of 6, up from 0 of 4. The two left are about what web adds

QuestionYou pickedRight answer
Web vs non-web environment"three different sources instead of the system ones"the same two, plus three more
A <context-param> from web.xml — which can see it?"both"StandardServletEnvironment only

It's Java inheritance. This is a simplified version of the Spring 5 source:

public class StandardServletEnvironment extends StandardEnvironment {   // ← EXTENDS
    protected void customizePropertySources(MutablePropertySources sources) {
        sources.addLast(servletConfigInitParams);
        sources.addLast(servletContextInitParams);
        if (jndiAvailable) sources.addLast(jndiProperties);
        super.customizePropertySources(sources);   // ← then adds systemProperties + systemEnvironment
    }
}

The web class is a subclass, and it calls super, so it keeps everything the non-web one has. "Instead of" would mean losing env vars in a web app, and you already knew env.getProperty("HOME") works there.

<context-param>: the servlet container reads web.xml and exposes the values through the ServletContext. A non-web app has no web.xml and no ServletContext object at all, so there's nowhere for the value to come from. That makes it "servlet" → web only, the same rule you applied correctly to the property-source names.

Rule to say before ticking: "Servlet environment extends the standard one: same two, plus three. Anything from web.xml needs a ServletContext, so web only."

6 · What a BPP receives 1 miss

Your pick

postProcessBeforeInitialization gets the object, not the definition

You picked "the bean definition". In the same block you got the order right, and you got "which receive the instance?" right in the retry.

Read the method name: Initialization. Only an object gets initialised, through @PostConstruct and init methods. A definition is never initialised. The signature is postProcessBeforeInitialization(Object bean, String beanName). Definitions are the BFPP's job, and it gets the whole factory.

Rule to say before ticking: "'Initialization' in the name means it gets an object. 'BeanFactory' in the name means it gets the factory, which holds the definitions."

True or false: the options you keep ticking

Each of these is an option you've ticked, or left out, at least once across the paper and the three revision pages. Answering one statement at a time trains the habit that fixes under-selection: every option gets its own yes or no.

Retry the 19, exact wording

The 19 questions you missed on revision 2, reshuffled. Do this last. On each "select all", give every option a yes or no before you click Check, and if an option feels familiar, check it against the rule anyway.

Next step. Tomorrow, do blocks 1 and 2 and the true-or-false block without rereading. They cover 11 of today's 19. If they're at full marks, the next useful step is a new mixed practice paper rather than a fourth revision, to see whether this holds on questions you've never seen. Or say "build the Spring Core clinic".
← Dashboard ← Revision 2 Revision 1 Review #21