Direct Bean Call Without Proxy

ID

java.bean_methods_singleton_invoked_config

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

best-practice, reliability

Description

Reports a method that calls a @Bean method directly (beanMethod() or this.beanMethod()) inside a @Configuration(proxyBeanMethods = false) class, when the called method has no scope annotation or is explicitly scoped singleton. Disabling proxyBeanMethods removes the CGLIB subclass that would otherwise intercept the call and return the already-created bean, so the call runs as an ordinary Java method invocation.

Rationale

proxyBeanMethods = false puts @Bean methods in "lite" mode: nothing intercepts calls to them, so every direct call builds a brand-new object. For a bean that is meant to be a shared singleton, each caller ends up with its own instance instead of the one already registered in the application context.

// Bad: connectionPool() is called directly, so every consumer gets its own pool
@Configuration(proxyBeanMethods = false)
class DataAccessConfig {

    @Bean
    public ConnectionPool connectionPool() {
        return new ConnectionPool();
    }

    @Bean
    public QueryRunner queryRunner() {
        return new QueryRunner(connectionPool());
    }
}

Remediation

Request the dependency as a method parameter instead of calling the @Bean method directly; Spring resolves the parameter from the context, so every caller shares the same instance regardless of proxying.

// Good: the pool is injected, so every caller shares the one managed instance
@Configuration(proxyBeanMethods = false)
class DataAccessConfig {

    @Bean
    public ConnectionPool connectionPool() {
        return new ConnectionPool();
    }

    @Bean
    public QueryRunner queryRunner(ConnectionPool connectionPool) {
        return new QueryRunner(connectionPool);
    }
}

© 2026 Xygeni. All rights reserved