Reputation: 1994
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
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
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
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:
<bean id="proeprtyLoader" class="org.stalwartz.config.PropertyLoader"></bean>
@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
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
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
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