2

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.

malejpavouk
  • 4,297
  • 6
  • 41
  • 67

1 Answers1

0

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.

Abhinav Sarkar
  • 23,534
  • 11
  • 81
  • 97
  • Are you sure this will work? I cant verify it at the moment, but it seems to me, that it has the same problem as my code. The ApplicationContext will not be autowired, as it is not ready at the moment (context is being initialized and cannot be initialized prior to construction of the Logger, because the logger is part of a Controller singleton bean). Hence the AnnotationBeanConfigurerAspect will not have access to the ApplicationContext and it wont be able to autowire it. – malejpavouk Dec 17 '13 at 12:40