Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I inject beans into a scope implementation?

I'm writing my own scope (i.e. a class which implements org.springframework.beans.factory.config.Scope) and I need some beans injected. How do I do that?

Background: Spring must create all scope beans first so that I can define which beans go into the scope. But what about beans that I need to build the scope in the first place?

like image 564
Aaron Digulla Avatar asked Aug 17 '12 12:08

Aaron Digulla


1 Answers

I came up with this workaround which seems to be pretty safe but I'd like to hear comments (or maybe my answer gives you some better ideas):

  1. Define the scope and give it setters (instead of using @Autowired)
  2. Create a "scope configurer" bean:

    public CustomScopeConfigurer {
        @Autowired private Foo foo;
        private CustomScope scope;
    
        public CustomScopeConfigurer( CustomScope scope ) {
            this.scope = scope;
        }
    
        @PostConstruct
        public void initScope() {
            scope.setFoo( foo );
        }
    }
    

    This configurer bean must not be lazy.

Reasoning:

  1. The scope itself can't use autowiring because it is created before the first bean. While it might be created later, you can be sure that it will be created before every other bean. So autowiring can't work reliably.

  2. The configurer bean will be created alongside all the other beans but after the scope. So autowiring will work for it.

  3. Since the configurer bean isn't initialized lazy, it will be created before the rest of the application can see the application context. This means that no beans for the scope (i.e. beans with @Scope("custom")) can have been created at this time - the scope can't be "active", yet -> Spring won't have tried to put any beans into it, yet.

  4. The scope itself is usually created as a static constant somewhere. That's why we have to pass it as an argument to the constructor.

like image 150
Aaron Digulla Avatar answered Sep 20 '22 03:09

Aaron Digulla