Explain the difference between the * and .. wildcards in an execution() pointcut, giving package, type, method-name, and parameter examples.
answer
- = one slot, .. = many slots
- .. only in package paths + params
- service.*.* = direct only
- service..*.* = + sub-packages
- (String, ..) prefix / (.., String) suffix
basics
~10 s- matches exactly one item (one name segment, one type, one parameter). .. matches zero or more — in package position it spans sub-packages, in the parameter position it spans any number of arguments.
solid answer
~40 s`*` is the single-element wildcard and `..` is the multi-element wildcard. In a method name, `get*` matches names starting with get; `*` alone matches any single method name. In a return/param type, `*` means any one type. In a package path, `com.app.*` matches types directly in that package only, while `com.app..` matches com.app plus all sub-packages. In parameters, `(*)` means exactly one argument, `(*, *)` exactly two, whereas `(..)` means zero-or-more arguments; you can mix them: `(String, ..)` is a String followed by anything. The key mental model: `*` = 'exactly one slot', `..` = 'any number of slots including none' — and `..` only appears in package paths and parameter lists.
code
java · 20 lines@Aspect
@Component
public class WildcardAspect {
// Only classes DIRECTLY in com.app.service (NOT sub-packages)
@Pointcut("execution(* com.app.service.*.*(..))")
public void directOnly() {}
// com.app.service AND every sub-package
@Pointcut("execution(* com.app.service..*.*(..))")
public void includingSubPackages() {}
// Exactly two args, first is a String, second any type
@Pointcut("execution(* com.app..*(String, *))")
public void stringThenAny() {}
// A String somewhere as the LAST argument, any others before
@Pointcut("execution(* com.app..*(.., String))")
public void trailingString() {}
}go deeper
Should know * = one and .. = many at a high level.
Should give correct package and parameter examples and know the single-dot trap.
Should explain positional legality of .. and the prefix/suffix parameter forms.
Should connect wildcard breadth to performance and 'advice not firing' debugging.
## Two wildcards, two jobs AspectJ pointcuts use exactly two wildcards inside `execution()`: - **`*`** — matches **one** item. One method-name (or part of one), one type, one type-name segment, or exactly **one** parameter. - **`..`** — matches **zero or more** items. It is only legal in **two positions**: inside a **package/type path** (spanning nested packages) and inside the **parameter list** (spanning any number of arguments). ## By position ### Method name - `*` → any method name (`execution(* *(..))`) - `find*` → names starting with `find` - `*ById` → names ending with `ById` - `*` can also be a fragment: `get*Name` matches `getFirstName`, `getName`. ### Return / parameter type - `*` → any single type: `execution(* find*(*))` = one arg of any type. - You cannot write `..` as a return type — return type is a single required slot. ### Package / declaring type - `com.app.service.*` → types **directly** in `com.app.service` (not `com.app.service.impl`). - `com.app.service..*` → types in `com.app.service` **and all sub-packages** (`..` then `*` for the class name). - `*Service` → any type name ending in Service. - `com.app..*Service` → any `*Service` type anywhere under `com.app`. ### Parameters - `()` → no parameters. - `(*)` → exactly one, any type. - `(*, *)` → exactly two, any types. - `(..)` → zero or more, any types. - `(String, ..)` → String first, then anything. - `(.., String)` → anything, ending in a String. - `(*, .., String)` → a first arg of any type, then anything, then a trailing String. ## The classic trap `execution(* com.app.service.*.*(..))` does **NOT** cover sub-packages — the `.*.` in the middle is 'any class **directly** in com.app.service'. To include sub-packages you must use the double dot: `execution(* com.app.service..*.*(..))`. Interviewers love this one. ## Why it matters A too-broad `..` in a package path silently advises far more beans than intended (performance + surprising behavior); a too-narrow single `*` silently misses beans in sub-packages (the aspect appears not to run). Getting `*` vs `..` right is the single most common source of 'my advice isn't firing' bugs.
- Why might an aspect 'silently not fire' on classes in an impl sub-package?The pointcut probably used a single dot (com.app.service.*.*) which matches only types directly in the package. Sub-packages like com.app.service.impl need the double-dot form com.app.service..*.*.
- Can .. be used as a return-type pattern?No. The return type is a single mandatory slot, so only * or a concrete type is valid there. .. is legal only in package paths and parameter lists.
saying these in an interview costs you the question
- Claiming * matches multiple parameters or multiple packages
- Thinking com.app.service.* includes sub-packages
- Using .. as a return type
- Believing (..) and (*) are interchangeable