{"record":{"id":"f5577b2a69fd0e87","repo":"spring-projects/spring-framework","slug":"can-only-use-global-advisors-or-interceptors-with","errorCode":null,"errorMessage":"Can only use global advisors or interceptors with a ListableBeanFactory","messagePattern":"Can only use global advisors or interceptors with a ListableBeanFactory","errorType":"exception","errorClass":"AopConfigException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java","lineNumber":425,"sourceCode":"\t */\n\tprivate synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {\n\t\tif (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) {\n\t\t\tif (this.beanFactory == null) {\n\t\t\t\tthrow new IllegalStateException(\"No BeanFactory available anymore (probably due to serialization) \" +\n\t\t\t\t\t\t\"- cannot resolve interceptor names \" + Arrays.toString(this.interceptorNames));\n\t\t\t}\n\n\t\t\t// Globals can't be last unless we specified a targetSource using the property...\n\t\t\tif (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&\n\t\t\t\t\tthis.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {\n\t\t\t\tthrow new AopConfigException(\"Target required after globals\");\n\t\t\t}\n\n\t\t\t// Materialize interceptor chain from bean names.\n\t\t\tfor (String name : this.interceptorNames) {\n\t\t\t\tif (name.endsWith(GLOBAL_SUFFIX)) {\n\t\t\t\t\tif (!(this.beanFactory instanceof ListableBeanFactory lbf)) {\n\t\t\t\t\t\tthrow new AopConfigException(\n\t\t\t\t\t\t\t\t\"Can only use global advisors or interceptors with a ListableBeanFactory\");\n\t\t\t\t\t}\n\t\t\t\t\taddGlobalAdvisors(lbf, name.substring(0, name.length() - GLOBAL_SUFFIX.length()));\n\t\t\t\t}\n\n\t\t\t\telse {\n\t\t\t\t\t// If we get here, we need to add a named interceptor.\n\t\t\t\t\t// We must check if it's a singleton or prototype.\n\t\t\t\t\tObject advice;\n\t\t\t\t\tif (this.singleton || this.beanFactory.isSingleton(name)) {\n\t\t\t\t\t\t// Add the real Advisor/Advice to the chain.\n\t\t\t\t\t\tadvice = this.beanFactory.getBean(name);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// It's a prototype Advice or Advisor: replace with a prototype.\n\t\t\t\t\t\t// Avoid unnecessary creation of prototype bean just for advisor chain initialization.\n\t\t\t\t\t\tadvice = new PrototypePlaceholderAdvisor(name);\n\t\t\t\t\t}","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java#L407-L443","documentation":"Thrown as AopConfigException by ProxyFactoryBean.initializeAdvisorChain when an interceptorNames entry ends with the global suffix '*' but this.beanFactory is not a ListableBeanFactory. Resolving '*' (or 'prefix*') requires enumerating beans by type, which only ListableBeanFactory supports. The check is at lines 423-427.","triggerScenarios":"Providing ProxyFactoryBean with a custom BeanFactory that only implements BeanFactory (not ListableBeanFactory) and using a global advisor pattern in interceptorNames. Standard ApplicationContexts use DefaultListableBeanFactory, so this is rare outside custom wiring.","commonSituations":"Programmatic setup where setBeanFactory is called with a non-listable factory; testing harnesses injecting a minimal BeanFactory stub; legacy custom BeanFactory implementations.","solutions":["Use a ListableBeanFactory (DefaultListableBeanFactory or any ApplicationContext) as the backing factory.","If you must keep a non-listable factory, replace global patterns ('global*') with explicit bean names in interceptorNames."],"exampleFix":"// before\nProxyFactoryBean fb = new ProxyFactoryBean();\nfb.setBeanFactory(nonListableFactory);\nfb.setInterceptorNames(\"global*\");\n\n// after\nProxyFactoryBean fb = new ProxyFactoryBean();\nfb.setBeanFactory(new DefaultListableBeanFactory()); // ListableBeanFactory\nfb.setInterceptorNames(\"global*\");\n// or: fb.setInterceptorNames(\"advisor1\",\"advisor2\");","handlingStrategy":"validation","validationCode":"if (Arrays.stream(interceptorNames).anyMatch(n -> n.endsWith(\"*\"))\n    && !(beanFactory instanceof ListableBeanFactory)) {\n  throw new IllegalStateException(\"Global advisor patterns require a ListableBeanFactory\");\n}","typeGuard":"static boolean supportsGlobals(BeanFactory bf) { return bf instanceof ListableBeanFactory; }","tryCatchPattern":"try { Object p = pfb.getObject(); }\ncatch (AopConfigException e) {\n  if (e.getMessage().contains(\"ListableBeanFactory\")) { /* swap factory or remove '*' names */ }\n  throw e;\n}","preventionTips":["Use a DefaultListableBeanFactory (any ApplicationContext) when relying on global patterns.","Avoid '*' patterns in interceptorNames for unit tests that inject minimal bean factories."],"tags":["spring-aop","proxyfactorybean","beanfactory","configuration"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}