Jigar Naik
Jigar Naik

Reputation: 1994

@PostConstruct spring does not get called without bean declaration

Why post construct does not get called without putting bean in applicationContext.xml

Here is my class which contains @PostConstruct annotation.

package org.stalwartz.config;

import javax.annotation.PostConstruct;
import javax.inject.Singleton;

@Singleton
public class PropertyLoader {

    @PostConstruct
    public void init() {
         System.out.println("PropertyLoader.init()");
    }
}

Below is my applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
 http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans.xsd 
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context.xsd 
 http://www.springframework.org/schema/mvc 
 http://www.springframework.org/schema/mvc/spring-mvc.xsd 
 http://www.springframework.org/schema/tx 
 http://www.springframework.org/schema/tx/spring-tx.xsd 
 http://www.directwebremoting.org/schema/spring-dwr
 http://www.directwebremoting.org/schema/spring-dwr/spring-dwr-3.0.xsd">

<dwr:annotation-config />
<dwr:annotation-scan base-package="org.stalwartz" scanDataTransferObject="true" scanRemoteProxy="true" />
<dwr:url-mapping />

<!--  <bean id="proeprtyLoader" class="org.stalwartz.config.PropertyLoader"></bean>  -->

<dwr:controller id="dwrController" debug="false">
    <dwr:config-param name="activeReverseAjaxEnabled" value="true" />
</dwr:controller>

<context:annotation-config>
    <context:component-scan base-package="org.stalwartz" annotation-config="true"></context:component-scan>
</context:annotation-config>

<mvc:annotation-driven />
...
...
...
</beans>

Looks simple, but it does not work without uncommenting bean declaration.

Upvotes: 5

Views: 24921

Answers (6)

jamal mousavi
jamal mousavi

Reputation: 15

add this dependency to pom.xml

<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>

  

Upvotes: 1

ArifMustafa
ArifMustafa

Reputation: 4935

by default a bean is singleton scoped in Spring, and @PostConstruct is usually used for service beans and service beans must scoped prototype and here because you need multiple objects for that particular class, Spring will provide you singleton instance.

also by doing this spring will attempt multiple times to find this service bean and finally throws below exception:

java.lang.NoClassDefFoundError: Could not initialize class org.springframework.beans.factory.BeanCreationException

so try like this in annotation way:

package org.stalwartz.config;

import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype") //you have to make it prototype explicitly
public class PropertyLoader {

    @PostConstruct
    public void init() {
         System.out.println("PropertyLoader.init()");
    }
}

Now every thing is good, and work fine for you.

Upvotes: 1

Lukas Risko
Lukas Risko

Reputation: 1489

In Spring environment initialization callback method (the one annotated by @PostConstruct) make sense only on spring-managed-beans. To make instance(s) of your PropertyLoader class managed, you must do one of the following:

  1. Explicitly register your class in context configuration (as you did)
    <bean id="proeprtyLoader" class="org.stalwartz.config.PropertyLoader"></bean>
  2. Let component scanning do the work (as you nearly did), but classes must be annotated by one of @Component, @Repository, @Service, @Controller.

Note from Spring documentation: The use of <context:component-scan> implicitly enables the functionality of <context:annotation-config>. There is usually no need to include the <context:annotation-config> element when using <context:component-scan>.

Upvotes: 4

Nikolay Rusev
Nikolay Rusev

Reputation: 4230

you are using @Singleton from javax.inject package which is not picked up as bean by spring container. Change it to :

package org.stalwartz.config;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class PropertyLoader {

    @PostConstruct
    public void init() {
        System.out.println("PropertyLoader.init()");
    }
}

and the spring will auto detect PropertyLoader and will include it in Spring container as bean via the @Component annotation and this bean will be with singleton scope

Upvotes: 1

nukie
nukie

Reputation: 681

Singleton is a scope annotation. It can be used to declare 'singletone' scope for a particular bean, but not instantiate it. See this article.

If you want to instantiate your class as singleton you can try Spring Service annotation.

@Service
public class PropertyLoader {

    @PostConstruct
    public void init() {
         System.out.println("PropertyLoader.init()");
    }
}

Also, you can replace annotation-config tag with component-scan. Here is a good article about differences of annotation-config and component-scan tags.

Upvotes: 1

mommcilo
mommcilo

Reputation: 946

Because putting bean in applicationContext.xml you are adding bean to Spring container, which has interceptor for this annotation. When Spring inject beans it checks @PostConstruct annotation, between others.

When you call simple new PropertyLoader() JVM will not search for the @PostConstruct annotation.

From doc of @PostConstruct annotation:

The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization. This method MUST be invoked before the class is put into service. This annotation MUST be supported on all classes that support dependency injection. The method annotated with PostConstruct MUST be invoked even if the class does not request any resources to be injected.

Upvotes: 1

Related Questions