Skip to content

Doc: Static @Bean methods cannot refer to each other with Spring scoping semantics [SPR-13118] #17709

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spring-projects-issues opened this issue Jun 12, 2015 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: task A general task
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jun 12, 2015

Johannes Zick opened SPR-13118 and commented

In our project, we use a custom Scope that can be controlled to some degree by the application. The Bean is declared in a @Configuration class using the @Bean annotation. The same class contains the CustomScopeConfigurer declaration referencing the Scope by method name.

@Configuration
public class Configuration
{
    @Bean
    static CustomScope getCustomScope()
    {
        return new CustomScope();
    }

    @Bean
    static CustomScopeConfigurer getCustomScopeConfigurer()
    {
        CustomScopeConfigurer customScopeConfigurer = new CustomScopeConfigurer();
        customScopeConfigurer.addScope("customScope", getCustomScope());
        return customScopeConfigurer;
    }
}

To control the custom Scope, we tried to inject it using @Autowired. This resulted in a new Bean being created. To access the Bean being used internally, we have to inject the ApplicationContext, retrieve the BeanFactory, then the registered Scope.

Usually, one would expect to have easy access to the custom Scope, since it is declared in the same @Configuration class. But apparently it lives in a completely separate Context. I can access it, however, via public methods.

I would highly recommend to change this, and add a word or two to the Javadocs. Either have it in a separate Context and not accessible, or allow access and make it injectable. The current behavior is inconsistent and not documented, as far as I can tell.


Affects: 4.1.5

Issue Links:

Referenced from: commits f58e1db

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

The root of the problem is the static nature of those @Bean methods: For regular, non-static @Bean methods, the container overrides such methods to allow for calls between @Bean methods, preserving the Spring scoping semantics that way. However, due to the technical mechanism used (subclassing via CGLIB), this cannot work for static methods.

So in your scenario, the getCustomScope() call in the getCustomScopeConfigurer method simply calls the other method without any interception or container treatment, i.e. with regular Java method call semantics. It'll get a fresh CustomScope instance that way which the container is not aware of. If you're then also requesting a CustomScope via the container, you'll get a managed singleton bean according to the @Bean getCustomScope declaration. Unfortunately, that managed singleton is different from the instance used by your CustomScopeConfigurer.

I hope the explanation above makes sense. Point taken that this isn't properly documented, so I'm turning this into a documentation task.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Johannes Zick commented

Ah, that clears this up.

The next question is: Can I turn it into a non-static method safely? There is a warning issued that some annotations will not work if the CustomScopeConfigurer bean method is not static. Again, it is not exactly clear to me what the intended way is.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

It's generally advisable to declare post-processor beans via static {{@Bean} methods. I've added a basic discussion of static {{@Bean} methods to the reference documentation now, including a note on post-processor beans.

With static methods, you could simply keep the CustomScope instance in a static field, expose it via a static getCustomScope method and also use the field in your CustomScopeConfigurer factory method.

Juergen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: task A general task
Projects
None yet
Development

No branches or pull requests

2 participants