In this post I shall cover the JSR250 annotations. Introduced in Spring 2.5, it added support for JSR-250 based annotations which include @Resource, @PostConstruct and @PreDestroy annotations. In my previous articles I have explained about the some of the popular annotations in Spring @Required, @Autowired and @Qualifier. Also please read about How to write Custom Spring Callback Methods?
@Resource vs @Autowired
@Resource is similar to @Autowired in functionality. @Autowired is Spring’s Annotation(only usable in Spring) whereas @Resource is JSR-250 Common Annotation equivalent (works the same in Java EE 5). Though the functionality for the two annotations being same, @Autowired is the only annotation that you can put on constructors.
By default auto wiring is done by object type. If you have two beans of the same type, then there is ambiguity that Spring can’t figure out which of the two beans to inject. That is when @Qualifier is used. It helps fix the ambiguity and tell Spring which of the two beans to inject. Use @Qualifier with @Autowired. With @Resource you can just put the bean name in the annotation as an attribute.
@PostConstruct and @PreDestroy
These annotations are alternative methods for defining initialization and destruction callback functions which I covered in post Customizing callback methods.
Example using @Resource, @PostConstruct and @PreDestroy
The example in post, demostrates the use of @Resource, @PostConstruct and @PreDestroy annotations.
Let us have working Eclipse IDE in place and follow the following steps to create a Spring application:
- Create a project: Create a project with a name SpringAnnotationExamples and create a package com.javabeat.jsrannotations under the src directory in the created project.
- Add Libraries: Add required Spring libraries using Add External JARs option as explained in the article Customizing callback methods.
- Create source files: Create Java classes Product,Type and MainApp under the com.javabeat.jsrannotations package.
- Create configuration file: Create XML based configuration file BeansJSRAnnotation.xml under src directory.
The class Product.java, is simple POJO class having name,price and an object of Type class. Contents of Product.java are:
package com.javabeat.jsrannotations; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; public class Product { private Integer price; private String name; @Resource(name = "typeB") private Type type; public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public Type getType() { return type; } public String getName() { return name; } public void setName(String name) { this.name = name; } @PostConstruct public void init() { System.out.println("In init block of Product"); } @PreDestroy public void destroy() { System.out.println("In destroy block of Product"); } }
Here you note that we have used @Resource annotation. @PostConstruct and @PreDestroy are used for their respective lifecycle callback methods. Here you can see, I’ve used the @Qualifier annotation alongwith the @Autowired annotation.
The Type.java class is also a POJO class having a string object called “type”. Contents of Type.java are:
package com.javabeat.jsrannotations; public class Type { private String productType; public String getProductType() { return productType; } public void setProductType(String productType) { this.productType = productType; } }
Contents of MainApp are:
package com.javabeat.jsrannotations; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { AbstractApplicationContext context = new ClassPathXmlApplicationContext( "BeansJSRAnnotation.xml"); Product product = (Product) context.getBean("product"); System.out.println("Product Name : " + product.getName()); System.out.println("Price : " + product.getPrice()); Type productType = product.getType(); System.out.println(product.getName() + " is of type:" + productType.getProductType()); context.registerShutdownHook(); } }
Here you need to register a shutdown hook registerShutdownHook() method that is declared on the AbstractApplicationContext class. This will ensures a graceful shutdown and calls the relevant destroy methods.
Contents of BeansJSRAnnotation.xml are:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <context:annotation-config /> <!-- Definition for Product bean --> <bean id="product" class="com.javabeat.jsrannotations.Product" init-method="init" destroy-method="destroy"> <property name="name" value="ProductA" /> <property name="price" value="400" /> </bean> <bean id="typeA" class="com.javabeat.jsrannotations.Type"> <property name="productType" value="Export" /> </bean> <bean id="typeB" class="com.javabeat.jsrannotations.Type"> <property name="productType" value="Import" /> </bean> </beans>
As you can note here we are having two beans of same type.In Product.java I’ve used @Resource(“typeB”) it means we want to autowire Type property of Product with bean id=”typeB” in XML configuration file. You can also note that init-method and destroy-method attribute are used to specify the name of the method that has a return void, no argument method signature (init() and destroy method respectively from Product.java).
Execute the code
The final step is run the application. Once all the above code is ready execute and the below output appears on the console:
In init block of Product Product Name : ProductA Price : 400 ProductA is of type:Import In destroy block of Product
Summary
In this post I discussed with and example about the use of JSR250 annotations. In the next article I shall cover the JSR330 annotations(@Inject and @Named). If you are interested in receiving the future articles, please subscribe here.