spring-projects/spring-framework · error · IllegalArgumentException
Bean with name '{beanName}' is a singleton, but aspect insta
Error message
Bean with name '{beanName}' is a singleton, but aspect instantiation model is not singleton What it means
Thrown as an IllegalArgumentException from BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors() when an aspect bean declares a non-singleton per-clause (perthis/pertarget/pertypewithin) but the bean itself is registered as a singleton in the BeanFactory. The two are contradictory: a per-object aspect must produce a new instance per target, which a singleton-scoped bean cannot do. Spring catches this mismatch before attempting prototype-based instantiation.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java:126
if (this.advisorFactory.isAspect(beanType)) {
try {
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
aspectNames.add(beanName);
}
catch (IllegalArgumentException | IllegalStateException | AopConfigException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring incompatible aspect [" + beanType.getName() + "]: " + ex);
}
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;View on GitHub (pinned to 69bf83ad71)
Solutions
- Annotate the aspect bean with @Scope("prototype") so each advised target gets its own instance.
- Alternatively, change the aspect per-clause to singleton if per-object state is unnecessary.
- In XML, set scope="prototype" on the aspect bean definition.
Example fix
// before
@Aspect("pertarget(execution(* com.example.Target.*(..)))")
@Component
public class PerTargetAspect { ... } // singleton by default -> throws
// after
import org.springframework.context.annotation.Scope;
@Aspect("pertarget(execution(* com.example.Target.*(..)))")
@Component
@Scope("prototype")
public class PerTargetAspect { ... } Defensive patterns
Strategy: validation
Validate before calling
import org.aspectj.lang.reflect.AjTypeSystem;
import org.aspectj.lang.reflect.PerClauseKind;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
public static String requiredScope(Class<?> aspectClass) {
var kind = AjTypeSystem.getAjType(aspectClass).getPerClause().getKind();
return (kind == PerClauseKind.SINGLETON)
? ConfigurableBeanFactory.SCOPE_SINGLETON
: ConfigurableBeanFactory.SCOPE_PROTOTYPE;
}
// for a perthis/pertarget aspect bean, ensure scope is prototype before context refresh.
Type guard
import org.aspectj.lang.reflect.AjTypeSystem;
import org.aspectj.lang.reflect.PerClauseKind;
public static boolean needsPrototypeScope(Class<?> aspectClass) {
var k = AjTypeSystem.getAjType(aspectClass).getPerClause().getKind();
return k == PerClauseKind.PERTHIS || k == PerClauseKind.PERTARGET || k == PerClauseKind.PERTYPEWITHIN;
} Try / catch
// BeanFactoryAspectJAdvisorsBuilder catches IllegalArgumentException/IllegalStateException/AopConfigException // itself and logs at debug; raise logging to DEBUG to surface such incompatible aspects. // Otherwise validate bean scopes up front (see validationCode).
Prevention
- Always pair @Aspect("perthis(...)") / pertarget / pertypewithin with @Scope("prototype").
- Add a BeanFactoryPostProcessor that checks aspect beans' scopes match their per-clause.
- In XML, set scope="prototype" on per-object aspect beans.
When it happens
Trigger: Declaring a bean annotated @Aspect("perthis(...)") or @Aspect("pertarget(...)") without setting @Scope("prototype"); XML bean declaration with singleton='true' (the default) whose class is a perthis/pertarget aspect; a @Configuration @Bean method returning a non-singleton aspect without specifying prototype scope.
Common situations: Forgetting to add @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) on a perthis/pertarget aspect; copy-pasting an aspect that worked under native AspectJ (where Spring scope is irrelevant) into a Spring AOP auto-proxy context.
Related errors
- {aspectClass.getName()} uses percflow instantiation model: T
- {aspectClass.getName()} uses percflowbelow instantiation mod
- PerClause {ajType.getPerClause().getKind()} not supported by
- Cannot use PrototypeAspectInstanceFactory with bean named '{
- 'argumentNames' property of AbstractAspectJAdvice contains a
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/cf4c9c449e0005a0.
Report an issue: GitHub.