441

In a managed bean, @PostConstruct is called after the regular Java object constructor.

Why would I use @PostConstruct to initialize by bean, instead of the regular constructor itself?

2
  • 7
    I got the impression that constructor injection was generally preferred to allow dependencies to be final. Given that pattern, why is @PostConstruct being added to J2EE - they must have seen another use case surely? Commented Jan 10, 2018 at 8:58
  • @mjaggard my understanding is that @PostConstruct is not used to inject your dependencies appropriately, to make sure they are final, etc; it is used as an annotation for a utility that should be called exactly once even if the object is constructed multiple times by the IoC container. Not that I know how this would happen in the container, but it apparently can happen (see accepted answer). Commented Jun 29, 2021 at 17:06

5 Answers 5

589
  • because when the constructor is called, the bean is not yet initialized - i.e. no dependencies are injected. In the @PostConstruct method the bean is fully initialized and you can use the dependencies.

  • because this is the contract that guarantees that this method will be invoked only once in the bean lifecycle. It may happen (though unlikely) that a bean is instantiated multiple times by the container in its internal working, but it guarantees that @PostConstruct will be invoked only once.

Sign up to request clarification or add additional context in comments.

15 Comments

in case the constructor itself autowires all dependencies - then the bean can also be fully initialized in the constructor (after setting manually all autowired fields).
what's the case in which a bean's constructor may be called more than once?
Probably something like "passivation". If the container decides to store the bean on the disk store and then restore it from there.
It's not that unlikely to see the constructor called multiple times. When the container instantiates a proxy, you will see that constructor is called at least once for the proxy and once for the real bean.
Neither of these reasons are valid: (1) Spring itself advises against using Field injection, so don't do that (2) You can't call the constructor multiple times in a single instances lifecycle, as other folks pointed out.
|
153

You always should prefer constructor injection, but having that said, if for any reason you have to use field injection, in that case the main problem is that:

in a constructor, the injection of the dependencies has not yet occurred


Example

public class Foo {

    @Inject
    Logger LOG;
        
    @PostConstruct
    public void fooInit(){
        LOG.info("This will be printed; LOG has already been injected");
    }

    public Foo() {
        LOG.info("This will NOT be printed, LOG is still null");
        // NullPointerException will be thrown here
    }
}

Important

@PostConstruct and @PreDestroy have been completely [removed in Java 11](https://jaxenter.com/jdk-11-java-ee-modules-140674.html).

To keep using them, you'll need to add the javax.annotation-api JAR to your dependencies.

Maven

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

Gradle

// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'

7 Comments

in a constructor, the injection of the dependencies has not yet occurred. true with setter or field injection, but not true with constructor injection.
With @PostConstruct being removed in Java 11, how can we now handle this real world example with Java 11?
@tet As mentioned in answer, you need to use javax.annotation-api library. These annotations were removed in Java 11, but were already marked deprecated since Java 9.
I can still see @PostConstruct in java 11
@Rookie007 if you check in your classpath you will notice you're using javax.annotation-api jar
|
81

If your class performs all of its initialization in the constructor, then @PostConstruct is indeed redundant.

However, if your class has its dependencies injected using setter methods, then the class's constructor cannot fully initialize the object, and sometimes some initialization needs to be performed after all the setter methods have been called, hence the use case of @PostConstruct.

1 Comment

@staffman: plus one from my side. If i wish to initialise an inputtext field with a value fetched from database, I am able to do it with the help of PostConstruct, but fails when try to do the same inside the constructor. I have this requirement to initialise without the use of PostContruct. If you have time, can you please answer this one also: www.greatytc.com/questions/27540573/…
2

There is only really one reason - because you want to take an action that requires the object to be fully constructed, like passing the "this" reference to an executor.

All the other reasons only occur if you fail to write code according to best practices (e.g. using field injections instead of constructor injection, etc).

But, since Java is free to re-order instructions in constructors, you cannot depend on any one field being fully constructed before handing off a reference to the object to an executor (i.e, the this reference should not escape until the constructor is finished)

Comments

1

Also constructor based initialisation will not work as intended whenever some kind of proxying or remoting is involved.

The ct will get called whenever an EJB gets deserialized, and whenever a new proxy gets created for it...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.