Spring @Configurable in Spring singleton bean constructor

1.1k views Asked by At

We have run into interesting issue regarding Spring @Configurable annotation. Everything in my project is set-up properly for Compile-time weaving (AspectJ) and the instrumentation works as expected.

But the problem follows. We are constructing some clever logger, which might be initialized outside spring scope. So we have decided to make it @Configurable

@Configurable
public class Logger(){
   @Autowired A a;
}

We want to use this Logger inside Spring @Controller, which is by definition stateless (singleton), so we have:

@Controller
public class Controller {
   Logger l = new Logger();
}

But because Controller is singleton, then spring initializes its contents on the initial load and because the logger is in its constructor, it gets initialized prior to complete construction of the context itself and hence its property A is never initialized. The following pretty explanatory warning is printed out:

2013.12.16 18:49:39.853 [main] DEBUG  o.s.b.f.w.BeanConfigurerSupport - 
BeanFactory has not been set on BeanConfigurerSupport: 
Make sure this configurer runs in a Spring container. 
Unable to configure bean of type [Logger]. Proceeding without injection. 

Is there any way out of this issue.

Thanks in advance.

1

There are 1 answers

1
Abhinav Sarkar On

Instead of autowiring the dependency directly at initlization, do it later manually using a @PostConstruct callback:

@Configurable
public class Logger() {
    @Autowired private ApplicationContext appCtx;
    private A a;
    @PostConstruct private void init() {
        this.a = appCtx.getBean(A.class);
    }
}

This works because ApplicationContext is always initialized first and is always available for injection. However, this makes your code aware of Spring.

Better solution is not to use @Configurable and use a Spring managed factory instead for creating new Loggers.