What does the bean() pointcut designator do in Spring AOP, and how do you use it?
answer
- matches by Spring bean NAME not type
- wildcard: bean(*Service)
- Spring-AOP only, no AspectJ equivalent
- often AND-ed with execution()
- FactoryBean: matches the produced bean
basics
~10 sbean(name) limits advice to join points inside Spring beans whose bean name matches the given pattern. For example, bean(tradeService) advises only the bean named tradeService, no matter its type.
solid answer
~40 sbean(idOrNamePattern) is a pointcut designator that matches join points located within Spring beans identified by name. You give it a bean id/name, optionally with a * wildcard, e.g. bean(tradeService) or bean(*Service). It scopes advice by bean name rather than by class, method signature, or annotation. It is commonly combined with execution(...) to say "any method in beans named *Service". Because it works on Spring's bean-name registry, it is a Spring-AOP-only designator with no AspectJ equivalent. You use it in @Pointcut / @Before / @Around expressions just like execution() or within(): @Before("bean(*Service)") advises every advised method in beans whose name ends with Service.
code
java · 14 lines@Aspect
@Component
public class ServiceMonitoringAspect {
// Advise every advised method on any bean whose name ends in "Service"
@Before("bean(*Service)")
public void logEntry(JoinPoint jp) {
System.out.println("enter: " + jp.getSignature());
}
// Narrow to one specific bean by exact name
@AfterReturning("bean(tradeService)")
public void afterTrade() { /* ... */ }
}go deeper
Know it matches join points by bean NAME and supports the * wildcard.
Know it combines with execution() via && and that it targets names, not types.
Explain the Spring-only nature and naming-convention use cases vs type/annotation scoping.
Discuss FactoryBean matching, name-vs-alias semantics, and governance trade-offs of name-based advice.
## What bean() is In Spring AOP a **pointcut** is a predicate that selects **join points** (in Spring, always method executions on Spring beans). Spring supports the standard AspectJ pointcut designators (`execution`, `within`, `@annotation`, `args`, `target`, `this`, etc.) **plus one designator of its own**: `bean(idOrNamePattern)`. `bean(...)` matches join points that occur **within a Spring bean identified by its bean name** (the id/name in the `ApplicationContext`, e.g. the default `tradeService` derived from a `@Service` class `TradeService`, or an explicit `@Bean`/XML name). ## Syntax ``` bean(idOrNamePattern) ``` - The argument is a **bean name**, not a fully-qualified type. - A single `*` wildcard is supported inside the name: `bean(*Service)`, `bean(user*)`, `bean(*Repository)`. - It can be combined with the boolean operators `&&`, `||`, `!`: `bean(*Service) || bean(*Dao)`, `!bean(internal*)`. ## How you use it It appears anywhere a pointcut expression is expected — in an `@Aspect` class: ```java @Aspect @Component class AuditAspect { @Before("bean(*Service)") void audit(JoinPoint jp) { /* runs before every advised method of beans named *Service */ } } ``` Most often it is **AND-ed with a signature designator** to narrow both the bean and the method: ```java @Around("execution(* *(..)) && bean(orderService)") ``` ## What it matches on It matches on the **Spring bean name**, decided at proxy-creation time. That means: - Two beans of the **same class** but different names can be advised differently. - Renaming the bean (changing its id) changes what the pointcut selects, even though the code is unchanged. - For a `FactoryBean`, the match applies to the **exposed bean** produced by the factory (the object you get from `getBean(name)`), not to the `&name` factory object itself. ## Why it exists / when to use it It is the idiomatic way to scope advice **by naming convention** rather than by package, type, or annotation — e.g. "apply this transaction/monitoring advice to every bean whose name ends in `Service`." It is especially handy when you cannot annotate the target classes and their **types don't share a common package or supertype**, but they **do** follow a name convention. ## Key limitation `bean()` is a **Spring-AOP-only** designator. AspectJ has no notion of Spring bean names, so if you use `bean(...)` in a pointcut that is meant to be woven by the AspectJ weaver (LTW/CTW native AspectJ aspects), it is **not understood**. It only works within Spring's proxy-based AOP.
- Does bean(*Service) match by class name or bean name?By bean name (the id in the ApplicationContext). For a @Service TradeService the default bean name is tradeService, so bean(*Service) matches it because the NAME ends in 'Service' — but if you registered it under a different name it would not match, even though the class name still ends in Service.
- Can you use bean() with pure AspectJ load-time weaving?No. bean() is a Spring-AOP-only designator; the AspectJ weaver has no concept of Spring bean names, so it is not recognized outside Spring's proxy-based AOP.