Burak Aktas Software Engineer

CDI Dependency Injection @PostConstruct and @PreDestroy Example

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.

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;

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.

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.

@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;

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.