skip to content

@EnableMethodSecurity

@EnableMethodSecurity switches on the annotation-driven interceptors, with flags for the pre/post, @Secured and JSR-250 styles, replacing the older global annotation. Knowing it registers AOP advisors explains the caveats that follow.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What does @EnableMethodSecurity do, and what are its prePostEnabled, securedEnabled, and jsr250Enabled flags?

level: juniorimportance: must knowfreq 70%

answer

  1. @Configuration + @EnableMethodSecurity
  2. prePostEnabled defaults TRUE
  3. securedEnabled = @Secured (role list)
  4. jsr250Enabled = @RolesAllowed/@PermitAll/@DenyAll
  5. AOP proxy — self-invocation bypasses

basics

~10 s

@EnableMethodSecurity turns on security checks on individual methods (not just URLs). prePostEnabled activates @PreAuthorize/@PostAuthorize (on by default), securedEnabled activates @Secured, and jsr250Enabled activates @RolesAllowed. You put it on a @Configuration class.

solid answer

~40 s

@EnableMethodSecurity is the annotation (Spring Security 5.6+) you add to a @Configuration class to enable authorization on individual bean methods rather than only on HTTP requests. It registers AOP interceptors that evaluate security annotations before or after a method runs. Its three flags toggle which annotation families are active: prePostEnabled turns on Spring's @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter (and, importantly, it defaults to true); securedEnabled turns on the legacy role-list @Secured; jsr250Enabled turns on the JSR-250 annotations @RolesAllowed, @PermitAll, @DenyAll. You typically leave prePostEnabled on and only enable the others if your codebase uses those annotation styles. Method security is enforced through Spring AOP proxies, so calls must go through the proxy for the check to fire.

code

java · 16 lines
java
@Configuration
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
public class MethodSecurityConfig { }

@Service
public class AccountService {

    @PreAuthorize("hasRole('ADMIN')")            // prePostEnabled (default true)
    public void closeAccount(String id) { }

    @Secured("ROLE_ADMIN")                        // securedEnabled
    public void freeze(String id) { }

    @RolesAllowed("ADMIN")                        // jsr250Enabled
    public void reopen(String id) { }
}

go deeper

for a junior

Know it enables per-method checks and name the three flags with the annotations each turns on.

for a middle

Explain the defaults (prePostEnabled=true, others false) and that @PreAuthorize is SpEL while @Secured/@RolesAllowed are plain role lists.

for a senior

Explain the AOP-proxy enforcement path and the self-invocation gotcha, and advise which annotation family to standardize on.

for a principal

Discuss migration policy, meta-annotation/templated-expression support, and enabling multiple families safely across a large codebase.

## What it is `@EnableMethodSecurity` is a Spring Security annotation (introduced in **Spring Security 5.6**, GA in 5.8 / Spring Boot 3) that you place on a `@Configuration` class to enable **method-level authorization** — deciding whether a caller may invoke a specific bean method, as opposed to *web* authorization which guards HTTP request paths in the `SecurityFilterChain`. ```java @Configuration @EnableMethodSecurity // prePostEnabled = true by default public class MethodSecurityConfig { } ``` ## How it works under the hood When present, its `@Import(MethodSecuritySelector.class)` pulls in configuration that registers **Spring AOP advisors** (interceptor beans). Each secured bean is wrapped in a **proxy**; when a method annotated for security is called *through that proxy*, the matching interceptor runs an `AuthorizationManager` to grant or deny access, throwing `AccessDeniedException` on denial. ## The three flags - **prePostEnabled** — enables the Spring-native, SpEL-powered annotations: `@PreAuthorize` (check *before* the method), `@PostAuthorize` (check the *return value* after), `@PreFilter` (filter a collection/array *argument*), `@PostFilter` (filter the returned collection). **Unlike the old `@EnableGlobalMethodSecurity`, this flag defaults to `true`.** - **securedEnabled** — enables the legacy `@Secured` annotation, which takes a plain list of role strings, e.g. `@Secured("ROLE_ADMIN")`. No SpEL. Defaults to `false`. - **jsr250Enabled** — enables the Jakarta/JSR-250 standard annotations `@RolesAllowed("ADMIN")`, `@PermitAll`, `@DenyAll`. Defaults to `false`. ```java @EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true) ``` ## Which to use Prefer `@PreAuthorize` (SpEL, can reference method arguments via `#name`, principal, authorities) for anything expressive. Use `@Secured` / `@RolesAllowed` only for simple role checks or to match an existing convention. You can enable more than one family simultaneously; different annotations then apply to different methods. ## Key gotchas - **Proxy self-invocation**: a call from one method of a bean to another method *of the same bean* (`this.other()`) bypasses the proxy, so its security annotation is **not** enforced. Route through an injected reference or split beans. - **Public methods only** by default (Spring AOP CGLIB/JDK proxies can't advise `private`/`final` methods the usual way). - Where you put the annotation still matters: it must be on a **Spring-managed bean**. - Meta-annotations / templated authorization expressions are supported (a big reason it replaced the old annotation).

  • If you only write @EnableMethodSecurity with no arguments, which annotations work?
    Only the pre/post family — @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter — because prePostEnabled defaults to true while securedEnabled and jsr250Enabled default to false.
  • Why might a @PreAuthorize on your method never trigger?
    Common causes: the class isn't a Spring bean, the method is called via self-invocation (this.method()) so it skips the proxy, or the method is private/final and can't be proxied.

saying these in an interview costs you the question

  • Thinking prePostEnabled must be set explicitly (it defaults to true).
  • Believing @Secured supports SpEL expressions (it only takes role name strings).
  • Assuming method security guards URLs — it guards method calls; URL rules live in the SecurityFilterChain.
  • Expecting self-invoked (this.x()) annotated calls to be secured.

context

open as a page

Compare @PreAuthorize (prePostEnabled) with @Secured (securedEnabled) and @RolesAllowed (jsr250Enabled): when would you choose each?

level: middleimportance: should knowfreq 55%

basics

~20 s

@PreAuthorize takes a full SpEL expression, so it can check roles, method arguments, and custom logic — the most powerful. @Secured and @RolesAllowed only take plain role-name strings for simple checks. Prefer @PreAuthorize unless you want a standard/simple role list.

open as a page

A @PreAuthorize annotation on a service method is being ignored at runtime. What are the likely causes given how @EnableMethodSecurity works?

level: middleimportance: should knowfreq 50%

basics

~20 s

Method security uses AOP proxies. The check only runs when the call comes through the proxy. Common misses: calling the method from within the same bean (self-invocation), the class isn't a Spring bean, the method is private/final, or you forgot @EnableMethodSecurity / the right flag.

open as a page

Why did @EnableMethodSecurity replace @EnableGlobalMethodSecurity, and what changed?

level: seniorimportance: should knowfreq 45%

basics

~20 s

@EnableMethodSecurity (Spring Security 5.6+) replaces the deprecated @EnableGlobalMethodSecurity. It's built on the newer, simpler AuthorizationManager API instead of the old AccessDecisionManager/voter machinery, defaults prePostEnabled to true, and supports meta-annotations and custom SpEL beans more cleanly.

open as a page

How are method-security checks physically applied — how are the interceptors registered and ordered as advisors?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

@EnableMethodSecurity registers a set of AOP advisor beans (pointcut + interceptor pairs), one per annotation type. Spring proxies your secured beans; when a matching method is called, the advisor's interceptor runs an AuthorizationManager to allow or deny. Their run order is fixed by AuthorizationInterceptorsOrder.

open as a page