Why Use @Postconstruct

Why use @PostConstruct?

  • 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.

What are the differences between @PostConstruct and Autowired Constructor?

in the first case, if I'm going to use MyBean.class without in a none Spring framework project I'll need to pass SomeOtherBean so I know the object is created correctly. but in the second case, I would have done new MyBean() and then after I'll get NullPointerException when using it because the object depends on SomeOtherBean.
so the first one is much cleaner.

Spring boot how to use @PostConstruct correctly

PostContstruct semantics


The PostConstruct annotation is part of JSR 330 (Dependency Injection) and is not a Spring custom annotation.

The annotation specification dictates that the annotated method MUST run before the service being injected into context or translated into a service.

Spring supports the PostConstruct lifecycle hook allowing to perform extra post-initialization actions once a bean has been initialized, i.e., it had all its dependencies injected.

Async semantics


The Async annotation on the other hand is a Spring specific annotation allowing to mark a method or a type as being a candidate for asynchronous execution.

Alternative


In a case where you are interested into starting a background process as long as you application starts, you should better use the application lifecycle events and more specifically the ApplicationReadyEvent to spin your monitoring activity:

@Slf4j
@Service
@AllArgsConstructor
public class FileMonitorService {

private final AppProperties appProperties;

private final WatchService watchService;

private final RestTemplate restTemplate;

@EventListener(ApplicationReadyEvent.class)
@Async
public void startMonitoring() {
// ...
}
}

And don't forget to add the @EnableAsync annotation on your Spring Boot configuration type to activate the asynchronous processing feature.

JSF - what is the difference between @PostConstruct and direct method call from constructor?

If the bean has request scope, @PostConstruct will get executed every time. It will be called after the managed bean is instantiated, but before the bean is placed in scope. Such a method take no arguments, return void, and may not declare a checked exception to be thrown. Method may be public, protected, private, or package private. If the method throws an unchecked exception, the JSF implementation must not put the managed bean into service and no further menthods on that managed bean instance will be called.

public TrainingClassForm() {

}
@PostConstruct
public void init() {
if (this.trainingListModel.getListDataModel() != null) {
this.trainingListModel.getAllTrainingClasses();
}

}


Reffering you to this question of stack
In a managed bean, @PostConstruct is called after the regular Java object constructor.
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
@PostConstruct 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.

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
Also see this and this

How to call PostConstruct method when creating an object with new keyword

All the annotations honored by spring (@PostConstruct, @PreDestroy, @Autowired and many others) are applicable when the object is created by spring itself.
In this case spring can analyze the class, handle the annotations, etc.

When you instantiate by yourself (new Banana()) - spring doesn't even know that your object exists and hence can't call any of its method, so you're forced doing it by yourself.
So yes, in this case you will have to call the method annotated with @PostConstruct manually, which means that the @PostConstruct annotation is pretty useless can can be omitted at all.

How to use PostConstruct in Plain Java

The comments that were mentioned on your question already state it: if you don't use a framework or tool that handles the annotations, then no, there is no way that those @PostConstruct and @PreDestroy-methods get called. As a side-note: you could also write your own AnnotationProcessor, but you will probably ending up writing a framework, where you could just use something like a CDI container of your choice (e.g. Weld, OpenWebBeans, etc.).

Now, how could you solve it without annotations? It depends what you want to achieve.

For example, if it doesn't really matter, that the @PostConstruct isn't called exactly after the construction of the object, then an instance initalization block may serve your needs, e.g.

class Some {

{
// your initialization code... however! this is not the same as @PostConstruct
}
}

Regarding the @PreDestroy you could overwrite Object.finalize.

Be careful when you supply your own finalize-implementation and read some articles regarding it, before you do.

Both solutions however are not 1:1 substitutes of the annotations, but they may be what you are looking for.

Here is an example class:

class PreDestroyPostConstruct {

PreDestroyPostConstruct() {
System.out.println("constructor");
}

{
System.out.println("initialization block");
}

@Override
protected void finalize() throws Throwable {
System.out.println("finalize");
}
}

Demonstrating the output:

PreDestroyPostConstruct obj = new PreDestroyPostConstruct();
obj = null;
System.out.println("Program finishing");

Possible output:

initialization block
constructor
finalize
Program finishing

Note, that there is no guarantee that finalize is called before the "Program finishing"-part and it may even happen that it isn't called/finished before the VM shuts down.

Order of @PostConstruct and inheritance

@PostConstruct is the last thing to get executed in the initialization of a given managed bean, relative to its position in the inheritance chain. From the spec

The container must ensure that:

  • Initializer methods (i.e. @PostConstruct) declared by a class X in the type hierarchy of the bean are called after all injected fields declared by X or by superclasses of X have been initialized.

  • Any @PostConstruct callback declared by a class X in the type hierarchy of the bean is called after all initializer methods declared by X or by superclasses of X have been called, after all injected fields declared by X or by superclasses of X have been initialized.

Pro Tip: With CDI 2.0, you can use @Inject to declare an initializer method as an alternative @PostConstruct and the restriction that you can have only one in a given class. The difference here is that @PostConstruct is still executed last and is the only place you can be guaranteed that all injected components will be available.

@PostConstruct annotation and spring lifecycle

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



Related Topics



Leave a reply



Submit