Spring: Why is afterPropertiesSet() of InitializingBean needed when there are static and non-static initializers in Java?
Asked Answered
S

2

29

I have used afterPropertiesSet() to initialize class properties in Spring beans. Now I see that this task can be accomplished by Java's built in static and non-static initializers. What can I do with afterPropertiesSet() that I cannot with the initializer blocks?

Sanskritic answered 9/6, 2015 at 7:58 Comment(4)
No you cannot accomplish that. The static block is only for static stuff and will be invoked/executed when the class is loaded. You only have access to static variables not instance variables. The afterPropertiesSet or @PostConstruct is to initialize a particular object instance and not a class.Kea
@M.Deinum you comment qualifies as an answer. You can post it.Sanskritic
@M.Deinum when you post your answer, it is worth covering when the class constructor can and cannot be used to achieve the same goal.Chairmanship
@OP have you tried this? Surely that would be the easiest way to find out the issues with the approach.Chairmanship
K
73

Given the following class

public class MyClass implements InitializingBean {

    static { ... } // static initializer
    { ... }  // non-static initializer

    public void afterPropertiesSet() throws Exception { ... }
}

The static initializer block is only executed when the class is loaded by the class loader. There is no instance of that class at that moment and you will only be able to access class level (static) variables at that point and not instance variables.

The non-static initializer block is when the object is constructed but before any properties are injected. The non-static initializer block is actually copied to the constructor.

The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.

See also Static Initialization Blocks and http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html

The afterPropertiesSet or @PostConstruct annotated method is called after an instance of class is created and all the properties have been set. For instance if you would like to preload some data that can be done in this method as all the dependencies have been set.

If you only have mandatory dependencies you might be better of using constructor injection and instead of using InitializingBean or @PostConstruct put the initializing logic in the constructor. This will only work if all the dependencies are injected through the constructor, if you have optional dependencies set by set methods then you have no choice but to use @PostConstruct or InitializingBean.

Kea answered 9/6, 2015 at 8:27 Comment(4)
Can I use MyService(Dep1 dep1, Optional<Dep2> dep2Optional) as part of constructor & avoid @PostConstruct altogether?Putrefy
Can you share real life examples with us ?Roughen
@AshokKoyi Yes you can. If you handle all of your dependencies in the constructor call.Renee
I see a lot of people use init() method in the constructor block to set up their class/bean as part of initialization.Renee
S
1

M. Denium's answer is great. To add a shorter explanation:

Static and non-static initializers are Java features and run before main() is called and during object creation respectively. They cannot be deferred.

afterPropertiesSet() is a Spring Framework feature. It is a function Spring calls after dependency injection is complete for that class. E.g. If you have defined loggerService dependency for that class, you can call loggerService.log("MyClass is ready") in it. You cannot do it in the initializers as the dependency might not have been injected/set yet.

Sanskritic answered 18/7, 2023 at 13:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.