We have seen how to inject cdi beans by using qualifiers and producers so far. Additionally, every cdi bean has a lifecycle, and we can initialize and prepare to destroy any managed bean by using two common annotations; @PostConstruct
and @PreDestroy
. Methods annotated with these annotations are called bean lifecycle callbacks.
@PostConstruct
Due to the Weld Reference injection and initialization happens in this order;
- First, the container calls the bean constructor (the default constructor or the one annotated @Inject), to obtain an instance of the bean.
- Next, the container initializes the values of all injected fields of the bean.
- Next, the container calls all initializer methods of bean (the call order is not portable, don’t rely on it).
- Finally, the @PostConstruct method, if any, is called.
So, the purpose of using @PostConstruct
is clear; it gives you a chance to initialize injected beans, resources etc.
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person {
// you may have injected beans, resources etc.
public Person() {
System.out.println("Constructor is called...");
}
@PostConstruct
public void init() {
System.out.println("@PostConstruct is called...");
}
}
So, the output by injecting a Person bean will be;
1
2
Constructor is called...
@PostConstruct is called...
One important point about @PostConstruct
is, it won’t be invoked if you try to inject and initialize bean through producer methods. Because using a producer method means that you are programmatically creating, initializing, and injecting your bean with new
keyword.
@PreDestroy
The second lifecycle call back method for a bean is annotated with @PreDestroy
. It prepares the managed bean to get destroyed. It is used for cleaning up operations, or releasing any resources. Finally, the method annotated with @PreDestroy
is called by CDI container when the life cycle of bean is finished.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Person {
// you may have injected beans, resources etc.
public Person() {
System.out.println("Constructor is called...");
}
@PostConstruct
public void init() {
System.out.println("@PostConstruct is called...");
}
@PreDestroy
public void dispose() {
System.out.println("@PreDestroy is called...");
}
}
We can see a very simple example about the life cycle a Person bean in a test method.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RunWith(Arquillian.class)
public class PersonTest {
@Deployment
public static WebArchive createJavaTestArchive() {
return ShrinkWrap.create(WebArchive.class)
.addPackage("predestroy_and_postconstruct")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Inject
private Person person;
@Test
public void test() {
System.out.println("running test");
}
}
Output;
1
2
3
4
Constructor is called...
@PostConstruct is called...
running test
@PreDestroy is called...
Again like producer methods, if we try to destroy a bean with a disposer method then method annotated with @PreDestroy
won’t be invoked due to the same reason which applies for producer methods.
Comments powered by Disqus.