42

I'm new to Spring, I would like to know:

I have a java class annotated with @Component (spring) and inside I have a method annotated with @PostConstruct. The class is then referenced by @Autowired annotated field in another class. Can I assume that the class is only injected after @PostConstruct is called?

@Component
class AuthenticationMetrics {

    private static final MetricRegistry metrics = new MetricRegistry();

    final Counter requestsTotal;

    final Meter guestLogins;

    final Meter kfUserLogins;

    final Timer guestLoginResponseTime;

    final Timer kfLoginResponseTime;

    @PostConstruct
    public void populateMetricsRegistry() {
        metrics.counter("authentication.requests.totals");
    }
}
Jason Law
  • 965
  • 1
  • 9
  • 21
Daniele
  • 1,332
  • 1
  • 13
  • 24
  • 2
    Yes yuo can assume it... Spring first creates the bean, then checks the eventual @PostConstruct annotation and finally injects the bean. I see, in any case, that you are using a non spring object in the populateMetricsRegistry method. In this case for this object (metrics object) it's your own responsability to manage the correct lifecycle – Angelo Immediata Jun 21 '17 at 16:08
  • I'm confused about the _another class_. Your `AuthenticationMetrics` class will be instantiated, its fields will be injected (none in this sample), then `@PostConstruct` will be called. If you're injecting `AuthenticationMetrics` somewhere, it will be injected before that _somewhere_'s `@PostConstrtuct` is invoked. – Sotirios Delimanolis Jun 21 '17 at 16:08

3 Answers3

71

If you are asking is injection of given class happening after @PostConstruct in that bean is called, then the answer is yes - @PostConstruct is executed before bean is considered as "injectable"

If you are asking if @PostConstruct on given bean is executed after all injections has been done (on the same bean) - then yes - @PostConstruct is executed after injections are commited to given bean. This is the reason it exists. Normally you could put @PostConstruct actions into the constructor. However, when new object is created (constructor is called) injections are not performed yet - so any initialization that depends on injected objects would fail due to NPE. That is why you need @PostConstruct

Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • 2
    Hi, yes I'm asking if @PostConstruct is executed before bean is considered as "injectable", that what I wanted to know. Thanks! – Daniele Jun 21 '17 at 16:26
  • you can remove this part: "If you are asking if @PostConstruct execution means that bean is injected somewhere - then no." I will accept the answer. – Daniele Jun 22 '17 at 14:09
  • So does this mean that there is absolutely no use case for @PostConstruct when doing constructor injection? – Sebastiaan van den Broek Jun 12 '19 at 04:59
28

The handling of annotations such as @PostConstruct, @Resource, @PreDestroy is done via a BeanPostProcessor, in this case the CommonAnnotationBeanPostProcessor. You can see in the following diagram from Spring that these BPP's are handled after Dependency Injection but before Bean Ready For Use (Which means as much as injectable).

enter image description here

Nico Van Belle
  • 4,911
  • 4
  • 32
  • 49
  • what will be the next life cycle step after `@PostConstruct`? i want to append user details from `principal` to the `request header` through a custom `interceptor`..please help – Kalanka Jun 19 '19 at 07:15
  • @Kalanka maybe ask a new question for it? And link back to it here.;. :) – rogerdpack Oct 29 '20 at 16:09
6

Yes. Bean creation workflow is:

  1. constructior call
  2. @Autowired fields
  3. @Autowired setters
  4. BeanPostProcessor's postProcessBeforeInitialization(), i.e. @PostConstruct called by CommonAnnotationBeanPostProcessor
  5. InitializingBean.afterPropertiesSet()
  6. BeanPostProcessor's postProcessAfterInitialization()
  7. Bean is ready and can be injected to other bean
Vitalii
  • 431
  • 4
  • 11