42/60 for the second time today. The total didn't move, but underneath it, almost everything did. Testing hit 100%. Security stayed at 100% — the first time in eight attempts that any section has held a top score across two papers. Data Management went 57% → 75% hours after the topic clinic went up. Three of your six sections are now genuinely finished. What's left is small and specific: Spring MVC collapsed to 40%, and all three of its misses are the same single concept. Add the four fabricated names you ticked, and the route to 46 is unusually short — the ledger is below.
Read the top two rows first — they are new information. Until today, every section that reached a
high score fell back within one paper: Security went 100 → 60 → 33, Boot went 92 → 40. This time Security held
at 100% and Testing joined it. That is the first evidence that anything in this series sticks, and it
happened after two consecutive reviews covered the same material. Data Management's +18 is the second piece of
evidence — it came hours after the topic clinic, the one page that treats a section as a whole rather than as a
list of one paper's mistakes.
The clock is now the outlier. 28m 46s of 2h 10m — 22% of your time,
101 minutes unused, 29 seconds per question. Across four papers you have gone
45 → 49 → 40 → 29 minutes. You are now answering more than four times faster than the exam allows, and
six of today's eighteen misses were multiple ticks on one-answer questions.
You asked how to reach the pass mark. This paper answers it unusually precisely, because the 18 misses are not spread evenly — they sit in three buckets, and two of them are cheap.
| Bucket | Marks | What it costs you to fix |
|---|---|---|
| ① Spring MVC — one concept Q3, Q4, Q51 are all "what can a handler return, and who resolves it" |
3 | One table (below) plus Lesson 11. Roughly 20 minutes. |
② Fabricated names you ticked@BeanConfiguration, @TryInvoke, ConnectionHealthIndicator, server.timeout |
4 | No study at all — one question asked per option. Zero minutes. |
| ③ Facts you were already taught IoC ≠ DI (Q30) and the JavaScript-in-SpEL trap (Q21) — both in review #7, four hours earlier |
2 | Re-read two checklist lines. Two minutes. |
| ④ Genuinely new material (scopes, SpEL compilation, auto-config ordering, Specification API) | 9 | The real study. Worth doing — but you don't need it to pass. |
Buckets ① + ② + ③ come to 9 marks, and you need 4. Nothing in those three buckets requires learning a new subject — one is a single MVC table, one is a habit, and one is re-reading something you read this morning. That is the whole gap, twice over.
The last three columns are all 25 August — morning, afternoon, evening.
| Section | #5 · 19 Aug | #6 · 25 am | #7 · 25 pm | #8 · 25 eve | Verdict |
|---|---|---|---|---|---|
| Spring Security | 60% | 33% | 100% | 100% | HELD — first time anything has |
| Testing | 88% | 70% | 86% | 100% | Finished |
| Data Management | 36% | 75% | 57% | 75% | Recovered after the topic clinic |
| Spring Boot | 92% | 40% | 64% | 71% | Climbing back steadily |
| Spring Core | 71% | 57% | 65% | 61% | Never above 71% in eight attempts |
| Spring MVC | 67% | 67% | 75% | 40% | Best, then worst, in four hours |
| Overall | 70% | 58% | 70% | 70% | Flat total, healthier shape |
ConnectionHealthIndicator, server.timeout, @BeanConfiguration,
@TryInvoke. This is the third paper running where fabricated names are your single largest
recoverable bucket — 7 fakes in #7, 4 here. It costs nothing to fix and it is worth your entire gap.Each of these was a free mark. Not one of them appears anywhere in the Spring, Spring Boot or Actuator source — they are constructed by gluing real words together, which is exactly why they read as plausible.
| You ticked | The real thing |
|---|---|
ConnectionHealthIndicator (Q15) | DataSourceHealthIndicator, DiskSpaceHealthIndicator, RedisHealthIndicator… |
server.timeout (Q23) | server.tomcat.connection-timeout — timeouts are always server-specific |
@BeanConfiguration (Q37) | @Configuration and @Bean are two separate annotations |
@TryInvoke (Q49) | @Autowired(required = false), @Nullable, Optional<T> |
The habit, stated once: before ticking any option
that names a class, annotation or property, ask "have I actually seen this?" If the answer is
"it sounds right", that is a no. Real Spring names are shorter and more boring than the fakes —
@BeanConfiguration is a compound of two annotations you know; server.timeout is the
generic form of a property that only exists in specific forms.
Your answer is reconstructed from the exported result — if a line looks wrong, tell me and I'll fix it. Click the topic to jump to the full explanation.
| Q | Topic | What you answered | The answer |
|---|---|---|---|
| Q1 | Spring Data Specification API | "Requires Spring Boot" + "only works with Hibernate" | It builds queries dynamically at runtime |
| Q3 | Valid controller return types | "HttpServletRequest" | void · String · ModelAndView |
| Q4 | DispatcherServlet responsibilities | Under-selected — missed one of the two | Produces the response · extends HttpServlet |
| Q5 | How Boot eases JPA setup | "Provides drivers for all enterprise databases" | Starter · auto-config · properties · beans · repositories |
| Q11 | SimpleJpaRepository per interface | "False" | True — it's the default implementation |
| Q12 | @EnableAutoConfiguration | "Required on auto-config classes" + "enables component scanning" | Turns on auto-config · is inside @SpringBootApplication |
| Q15 | Built-in health indicators | "ConnectionHealthIndicator" — invented | DiskSpace · Elasticsearch |
| Q21 | What @Value accepts | "JavaScript expressions" — same fake as #7's Q53 | ${property} · #{SpEL} · literals · collections |
| Q23 | Customising the embedded server | "server.timeout" — invented | WebServerFactoryCustomizer · server.port |
| Q24 | Where @Transactional works | "On a private method" | Class level · public methods only |
| Q29 | SpEL IMMEDIATE compilation mode | Two wrong descriptions ticked | Compile ASAP; on failure throw, don't fall back |
| Q30 | "IoC is also known as DI" | "True" — taught in #3, #4 and #7 | False — DI is one technique for achieving IoC |
| Q36 | @AutoConfigureBefore, class missing | Three wrong options ticked | The ordering hint is ignored; the config still loads |
| Q37 | Java-based configuration annotations | "@BeanConfiguration" — invented | @Bean · @Import · @DependsOn |
| Q43 | Using a custom scope | Three wrong options ticked | It must be registered with the BeanFactory |
| Q44 | Scopes outside a web app | "Request scope" | singleton · prototype only |
| Q49 | @Autowired method, unresolvable parameter | "@TryInvoke" — invented | Throws · or make the parameter/method optional |
| Q51 | What a controller cannot return | "A logical view name" and "void" — the two most standard returns | An absolute path to the view |
40%, down from 75% four hours earlier — and this is the best news on the page. All three misses are the single question "what can a handler method return, and who turns that into a response?" One table fixes the whole section, and the section is 3 marks against a gap of 4.
| Return type | Valid? | What Spring does with it |
|---|---|---|
String | yes | a logical view name → handed to the ViewResolver |
ModelAndView | yes | model and view name together |
View (e.g. new JstlView(…), RedirectView) | yes | the view object itself — bypasses the resolver |
void | yes | view name inferred from the URL, or you wrote the response yourself |
Model / Map | yes | model attributes; view name inferred as for void |
a domain object + @ResponseBody | yes | serialised by an HttpMessageConverter |
ResponseEntity<T> | yes | body + status + headers |
an absolute path "/WEB-INF/views/home.jsp" | NO | the resolver would prefix/suffix it and fail |
HttpServletRequest / HttpServletResponse | NO | these are parameters, injected in — never returned |
The one sentence that carries the whole section:
a controller returns what to render (a name, a view, or a model) or the response body itself
(with @ResponseBody). It never returns the machinery — not the request, not the response, not a
filesystem path.
void, String, ModelAndView — HttpServletRequest is a parameterHttpServletRequest alongside the three correct
ones. It's a real class you've seen in controller signatures — but on the left of the
method, not the right.Spring injects the servlet objects into your method so you can read from them; returning one would tell the framework nothing about what to render:
@GetMapping("/hello")
public String hello(HttpServletRequest request) { // ← injected as a PARAMETER
log.info(request.getRemoteAddr());
return "helloView"; // ← returned: a view NAME
}
The parameter side of the contract is worth knowing in its own right, because it's the mirror
question: Spring can inject HttpServletRequest, HttpServletResponse,
HttpSession, Model, Locale, Principal, and anything annotated
@RequestParam/@PathVariable/@RequestBody/@RequestHeader.
DispatcherServlet doesHttpServlet — it does not resolve views itselfViewResolver) and the @EnableWebMvc claim,
which is the hard part.The DispatcherServlet is the front controller: it receives every request and
coordinates the components that do the actual work. Knowing who does what is the whole question:
| Step | Who does it |
|---|---|
| Receive the request | DispatcherServlet (it extends HttpServlet) |
| Find the handler for the URL | HandlerMapping |
| Invoke the handler method | HandlerAdapter |
| Turn a view name into a View | ViewResolver — not the DispatcherServlet |
| Render and send the response | DispatcherServlet, via the View |
And the registration fact, which was the fourth option:
@EnableWebMvc does not register a DispatcherServlet. It only switches on the MVC
infrastructure beans (HandlerMapping, HandlerAdapter, ViewResolver). The
servlet itself is registered by Spring Boot's auto-configuration (mapped to /), or by hand in
web.xml / a WebApplicationInitializer in a non-Boot app.
void are both fineThe distinction is between a logical name and a physical path:
| You return | Result |
|---|---|
"home" | resolver adds prefix + suffix → /WEB-INF/views/home.jsp ✅ |
"/WEB-INF/views/home.jsp" | resolver adds them anyway → /WEB-INF/views/WEB-INF/views/home.jsp.jsp ❌ |
new JstlView("/WEB-INF/views/home.jsp") | a View object — skips the resolver entirely ✅ |
That third row is the key insight, and it's why the question is fair: if you
genuinely need to name a physical path, you wrap it in a View object, because View
return values bypass resolution. A bare String is always treated as a logical name to be
resolved — which is exactly what makes an absolute path break.
Note the pattern across all three MVC questions: two of them hinged on a word — "cannot" here, and "return type" versus "parameter" in Q3. At 29 seconds per question, those are the words that get skipped.
71%, climbing steadily from 40% two papers ago. Two of these five were fabricated names.
DiskSpaceHealthIndicator and ElasticsearchHealthIndicator — there is no ConnectionHealthIndicatorConnectionHealthIndicator.
You were right to reject ApplicationHealthIndicator, which is the same kind of
fake.Health indicators are named after the technology they check, and each is auto-configured when that technology is on the classpath:
| Indicator | Registered when |
|---|---|
DiskSpaceHealthIndicator | always — checks free space against a threshold |
DataSourceHealthIndicator | a DataSource exists |
ElasticsearchHealthIndicator | the Elasticsearch client is present |
RedisHealthIndicator, MongoHealthIndicator, RabbitHealthIndicator, MailHealthIndicator, CassandraHealthIndicator | that client is present |
PingHealthIndicator | always — trivially returns UP |
The naming rule kills both fakes: "Connection" and "Application" name concepts, not
technologies. Overall application health isn't an indicator at all — it's the aggregate that
HealthEndpoint composes from every registered indicator, taking the worst status.
Two neighbouring facts: write your own by implementing HealthIndicator and annotating
it @Component (the bean name minus the suffix becomes the key in the JSON); and
management.endpoint.health.show-details defaults to never, so the individual indicators
are invisible until you set it to always or when_authorized.
WebServerFactoryCustomizer and server.port — there is no generic server.timeoutserver.timeout.
You correctly rejected the Jetty option, which is the subtler trap — swapping Tomcat for Jetty
still gives you an embedded server.Timeouts are always server-specific, because each container implements them differently:
| Setting | Property |
|---|---|
| Port | server.port (generic) |
| Context path | server.servlet.context-path (generic) |
| Connection timeout | server.tomcat.connection-timeout · server.jetty.connection-idle-timeout · server.undertow.no-request-timeout |
| Max threads | server.tomcat.threads.max |
The generic server.connection-timeout did once exist and was removed in Spring Boot
2.3 precisely because it couldn't map cleanly onto every container. So the shape to remember is: settings
every server shares are generic; settings only some servers have are namespaced by server name.
And the embedded-vs-external point from the third option: excluding
spring-boot-starter-tomcat and adding spring-boot-starter-jetty switches which
embedded server you use. To deploy to an external container you package as a WAR and extend
SpringBootServletInitializer.
@EnableAutoConfiguration does@SpringBootApplication — that's allThree annotations, three jobs, and the exam tests that you don't blur them:
| Annotation | Its one job |
|---|---|
@Configuration | this class declares @Bean methods |
@EnableAutoConfiguration | load auto-configuration classes conditionally from the classpath |
@ComponentScan | scan this package and below for stereotypes |
@SpringBootApplication = all three | |
On the other distractor: an auto-configuration class is annotated
@Configuration (or @AutoConfiguration in Boot 2.7+) and is registered in
META-INF/spring.factories — or, from Boot 2.7,
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. It never carries
@EnableAutoConfiguration itself; that annotation goes on your application, to say "go and
find them".
@AutoConfigureBefore(name = "…") when the class is missing@DependsOn instead". All three assume a missing reference is an error. It
isn't.The clue is in the attribute: name = "com.example.PreviousConfig" is a
String, not a class literal. Spring uses the string form precisely so that the class need not be
present — referencing it as PreviousConfig.class would require it on the classpath to even compile.
| Annotation | Orders | If the reference is missing |
|---|---|---|
@AutoConfigureBefore / @AutoConfigureAfter | auto-configuration classes | silently ignored — config still loads |
@AutoConfigureOrder(n) | auto-config classes, absolutely | n/a |
@DependsOn | beans | throws NoSuchBeanDefinitionException |
Why the design is like that: auto-configurations are contributed by JARs that may
or may not be present. An ordering hint that exploded whenever an optional starter was absent would make
every optional dependency mandatory. Ordering is a preference; the real gating is done by
@ConditionalOnClass, @ConditionalOnMissingBean and friends.
What the starter does give you — and note that the answer to "how does Boot help" is almost always "all of the above":
| Boot provides | Via |
|---|---|
| One dependency pulling the whole stack | spring-boot-starter-data-jpa → Hibernate, Spring Data JPA, spring-orm, spring-jdbc, HikariCP |
| Auto-configuration | DataSourceAutoConfiguration, HibernateJpaAutoConfiguration, JpaRepositoriesAutoConfiguration |
| Property-driven DataSource + HikariCP | spring.datasource.* → DataSourceProperties |
| The beans you'd otherwise hand-write | LocalContainerEntityManagerFactoryBean, JpaTransactionManager |
| Repository proxies | @EnableJpaRepositories from the @SpringBootApplication package |
| JDBC drivers | no — you add H2, Postgres, MySQL, Oracle yourself |
This is the same bean list as the Data Management clinic's manual-JPA question, seen from the other side: there, you wired those four beans by hand; here, Boot does it. Knowing both directions is what the exam is actually testing.
One behaviour worth carrying: Boot backs off, it does not merge. Declare your own
DataSource bean and DataSourceAutoConfiguration steps aside entirely — the same
@ConditionalOnMissingBean mechanism as the SecurityFilterChain case from review #7.
BeanFactory before any bean can use it@Scope("customScope")
looks complete, but the string has to resolve to something.@Scope("customScope") is only a lookup by name. If nothing has registered that
name, you get IllegalStateException: No Scope registered for scope name 'customScope' when the bean
is first created. Two steps are required:
// 1. implement the Scope interface
public class TenantScope implements Scope {
public Object get(String name, ObjectFactory<?> factory) { … }
public Object remove(String name) { … }
// …
}
// 2. register it — declaratively
@Bean
public static CustomScopeConfigurer scopes() { // note: static
CustomScopeConfigurer c = new CustomScopeConfigurer();
c.addScope("tenant", new TenantScope());
return c;
}
// 3. now this works
@Bean @Scope("tenant")
public TenantContext tenantContext() { return new TenantContext(); }
| Registration route | When |
|---|---|
CustomScopeConfigurer bean | declarative — the usual way |
ConfigurableBeanFactory.registerScope(name, scope) | programmatic |
The static on that @Bean method matters: CustomScopeConfigurer
is a BeanFactoryPostProcessor, so it must be instantiated before the enclosing
@Configuration class is fully processed. Same reason
PropertySourcesPlaceholderConfigurer is declared static.
singleton and prototype — the other four need a web-aware contextsession, so the boundary was half there.Six built-in scopes, split cleanly in two:
| Scope | Web only? | One instance per… |
|---|---|---|
singleton (default) | no | IoC container |
prototype | no | request to the container (a new one every time) |
request | yes | HTTP request |
session | yes | HTTP session |
application | yes | ServletContext |
websocket | yes | WebSocket session |
The rule underneath: the four web scopes are keyed off something that only exists in a web
container, so they need a WebApplicationContext. Using one in a plain context throws
IllegalStateException at runtime — not at startup, which is what makes it a real-world bug.
Two facts that ride along and are asked constantly: prototype beans get no destruction
callbacks (Spring forgets them after creation, so @PreDestroy never runs); and injecting a
prototype into a singleton gives you one instance forever — use ObjectProvider<T>,
@Lookup or a scoped proxy if you want a fresh one per call.
@Autowired method with an unresolvable parameter invented name@TryInvoke.
No such annotation exists in Spring — or, for that matter, anywhere in the Java
ecosystem.Three real outcomes, and the difference between two of them is where you put the optionality:
| Declaration | Behaviour when one parameter can't be resolved |
|---|---|
@Autowired (plain) | throws NoSuchBeanDefinitionException; the method never runs |
@Autowired(required = false) on the method | the whole method is skipped — no exception, no partial call |
@Nullable or Optional<T> on the parameter | the method is called, with null / Optional.empty() for the missing one |
@Autowired(required = false)
public void configureSlack(SlackClient client) { … } // skipped entirely if absent
@Autowired
public void configure(EmailClient email, @Nullable MetricsClient metrics) { … }
// always called; metrics may be null
Method-level skips, parameter-level injects null. That is the whole distinction,
and it's what the question was built around. For constructors the picture is slightly different:
required = false isn't meaningful there, so use Optional<T> or
@Nullable parameters for optional constructor dependencies.
@Value 2 misses@Value accepts identical distractor in #7's Q53 — ticked both times${property}, #{SpEL}, literals and collections — never JavaScript@Value("(() => 2 * 3)()").
This is the same fabricated option you ticked on Q53 four hours ago, and review #7 named
it explicitly: "SpEL has no lambda or arrow-function syntax at all."Three input forms, handled by three different subsystems — that's why the question is a good one:
| Form | Example | Processed by |
|---|---|---|
${…} property placeholder | @Value("${app.name}") | PropertySourcesPlaceholderConfigurer |
#{…} SpEL | @Value("#{3 * 2}") | SpelExpressionParser |
| plain text | @Value("John") | injected as a literal String |
| collections | @Value("${app.roles}") into List<String> | comma-separated values are split automatically |
Two details that turn up as follow-ups. A missing property throws at startup —
@Value("${nope}") fails the context; use ${key:default} for optional ones. And the two
forms can be combined: @Value("#{environment['my.key'] ?: 'fallback'}") uses SpEL to read a property
with an Elvis fallback.
Why this one is worth a moment's reflection. The same fake caught you twice in one day. Recognising the language a snippet is written in is a valid elimination — arrow functions are JavaScript, and no Java framework's expression language borrows them.
${} = property · #{} = SpEL · bare text = literal. No lambdas, no arrow functions — that's JavaScript.IMMEDIATE compilation modeBy default SpEL interprets expressions by walking the AST. The compiler generates real bytecode, which is much faster for repeated evaluation. Three modes decide when — and what happens when compilation isn't possible:
| Mode | Compiles | If compilation fails |
|---|---|---|
OFF (default) | never — always interpreted | n/a |
MIXED | after several interpreted runs | silently falls back to interpreted |
IMMEDIATE | as soon as possible — after the first interpreted evaluation | throws to the caller |
Read the two clauses separately. "After some number of runs" ⇒ MIXED. "As soon as possible" ⇒ IMMEDIATE. Then check the error half: MIXED is the forgiving one, IMMEDIATE is the strict one. The names carry both meanings — immediate compilation, immediate failure.
SpelParserConfiguration config = new SpelParserConfiguration(
SpelCompilerMode.IMMEDIATE, getClass().getClassLoader());
ExpressionParser parser = new SpelExpressionParser(config);
Not every expression is compilable — null-safe navigation, some projections and certain casts
aren't. That's the whole reason the two modes differ: MIXED degrades quietly, IMMEDIATE tells you. Compilation
only pays off for high-frequency evaluation (Spring Integration, Spring Batch); for a one-off
@Value at startup the bytecode generation costs more than it saves.
75%, up 18 points from this afternoon — the topic clinic did its job. These three are outside what that page covered, so they're genuinely new ground.
Specification APISpecification<T> wraps the standard JPA Criteria API in something
composable. Your repository extends JpaSpecificationExecutor<T> to gain
findAll(Specification<T>):
public interface Specification<T> {
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}
Specification<User> spec = Specification.where(hasLastName("Smith"))
.and(isActive());
List<User> users = userRepo.findAll(spec); // query assembled at runtime
Why "dynamic" is the point: derived query methods and @Query are both
fixed at compile time — one query per method. A search screen with eight optional filters would need 256 methods.
Specifications let you build the WHERE clause from whichever filters the user actually supplied.
On the two distractors: it's part of Spring Data JPA, so it works in any Spring application
with or without Boot; and it uses standard JPA Criteria, so any JPA-compliant provider works — Hibernate,
EclipseLink, OpenJPA. The pattern to notice is that both wrong options invented a dependency. Also note pagination
and sorting are not its job — that's Pageable and Sort, which you pass
alongside a specification.
SimpleJpaRepository for each repository interface"SimpleJpaRepository from the transactional angle (readOnly = true at class level); this
question asks the more basic fact that it exists at all.What happens when you declare an empty interface:
| Step | What Spring Data does |
|---|---|
| 1 | scans for interfaces extending Repository |
| 2 | creates a JDK dynamic proxy for each one |
| 3 | backs the proxy with an instance of SimpleJpaRepository |
| 4 | routes each call: custom fragment → derived query / @Query → the base class |
So save(), findById(), deleteAll() are literally
SimpleJpaRepository's methods. That's what connects three separate exam facts:
no @Repository is needed (the proxy is registered for you);
every call is already transactional (the base class is @Transactional(readOnly = true) with
write methods overriding); and repositoryBaseClass exists so you can swap this class for your
own.
@Transactional can be used proxy visibility · #4, #5, #7This is the CGLIB visibility rule from review #7 with one extra restriction on top. Two separate limits are in play:
| Where | Proxy mode (default) | AspectJ mode |
|---|---|---|
| class level | advises all public methods (a default; method annotations override) | all methods |
public method | advised | advised |
protected / package-private | not advised | advised |
private | not advised | advised |
Note the subtlety versus AOP in general. CGLIB can intercept
protected and package-private methods — that was review #7's Q17. But
@Transactional is narrower still, because
AnnotationTransactionAttributeSource is configured public-methods-only. So the transaction
rule is stricter than the proxy rule, and the two questions have different answers. That's exactly the kind of
distinction the exam likes.
The silently is what makes this dangerous in practice: no error at startup, no warning — the
method just runs without a transaction. Same category as self-invocation, which bypasses the proxy at
every visibility. Lifting either restriction means switching to
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ) with real weaving.
The relationship is containment, not equivalence:
| Inversion of Control | Dependency Injection | |
|---|---|---|
| What it is | a broad principle — the framework, not your code, controls creation and flow | one specific technique for realising it |
| Also includes | template methods, event callbacks, service locators, contextualised lookup | constructor, setter and field injection |
| Relationship | DI ⊂ IoC — every DI is IoC; not every IoC is DI | |
Why it keeps catching you is worth naming: in everyday Spring usage the terms are used interchangeably, and even the Spring docs slide between them. The exam is testing the strict definition, so the phrase "is also known as" / "is another name for" is the trigger — whenever you see it joining IoC and DI, the answer is false.
And a suggestion, since this is the fourth appearance: the fix isn't more reading. Write the sentence "DI is a subset of IoC" somewhere you'll see it, and answer the drill below rather than re-reading this paragraph. Recognition is what's failing here, not comprehension.
@Bean, @Import, @DependsOn — there is no @BeanConfiguration@BeanConfiguration.
A compound of two annotations you know well, which is exactly what makes it read as
real.The Java-config vocabulary, with what each one actually does:
| Annotation | Does |
|---|---|
@Configuration | marks a class as a source of bean definitions (CGLIB-proxied, so inter-@Bean calls return the singleton) |
@Bean | declares one bean from a method's return value |
@Import | pulls in another configuration class — how you modularise config |
@DependsOn | forces bean A to be initialised after bean B, where there's no injected dependency to express it |
@ComponentScan | finds stereotype-annotated classes |
@PropertySource | adds a properties file to the Environment |
@DependsOn is the one worth a second look, since it's the least familiar: use it when
the ordering matters but nothing is injected — a bean that registers a JDBC driver, or one that must initialise a
cache before another reads it. Compare it with @AutoConfigureBefore from Q36 above: same idea, but
that one orders configuration classes and ignores missing references, while @DependsOn
orders beans and throws.
HttpServletRequest/Response (they're parameters) and an absolute view pathHttpServlet and produces the response; ViewResolver resolves the view; @EnableWebMvc doesn't register the servletConnectionHealthIndicatorserver.tomcat.connection-timeout; only port and context-path are generic@ComponentScan; auto-config classes are registered in a file, not annotated with itCustomScopeConfigurer (a static @Bean) or registerScope()required=false on the method skips it · @Nullable/Optional on the parameter injects null${property}, #{SpEL}, literals and collections — no arrow functions; a missing property fails at startup unless you write ${key:default}JpaSpecificationExecutor; not Boot- or Hibernate-specific@Repository and already transactional@BeanConfigurationEight attempts in, three things are now settled.
Security and Testing are done — 100% each, and Security held it across two papers, which nothing had ever
done before. Data Management responds to the topic clinic — +18 the same day. Your under-selection
problem is gone — 5 marks in attempt #5, 1 today.
What remains is two topics and one habit: Spring MVC (3 marks, one table), Spring Core (7 marks, the
long game), and the fabricated-name check (4 marks, free). You do not need all of that. You need
four.