With release 2.5 of Spring we have a more complete support in Spring for annotation driven configuration. All of that XML configuration stuff can be set aside now. Release 2.0 had previously introduced some other annotations, @Transactional being my favourite.
Lets go through a quick sample. All of the code below I developed as a simple Java project in Eclipse (3.3).
1 2 3 4 5 |
package trial; public interface Greeter { public String getGreeting(); } |
Nothing special, just a simple interface.
1 2 3 4 5 6 7 8 9 10 11 12 |
package trial; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class GreeterImpl implements Greeter { @Autowired private Clock clock; public String getGreeting() { return "Good day. The time is now " + clock.getTime(); } } |
- @Service marks this as a component managed by Spring.
- @Autowired marks the field as a dependency which Spring will inject. You could provide a setter method for Clock and then have the @Autowired annotation against the method. But I am in favor of annotating the field itself. Why waste code lines just to do injection
Clock has a similar implementation. For the sake of completion here it is…
1 2 3 4 5 |
package trial; public interface Clock { public String getTime(); } |
1 2 3 4 5 6 7 8 9 10 11 |
package trial; import java.util.Calendar; import org.springframework.stereotype.Service; @Service public class ClockImpl implements Clock { @Override public String getTime() { return Calendar.getInstance().getTime().toString(); } } |
Here is the Spring configuration.xml file…
1 2 3 4 5 6 7 8 9 10 11 |
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans-2.5.xsd www.springframework.org/schema/aop www.springframework.org/schema/aop/spring-aop-2.5.xsd www.springframework.org/schema/context www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config /> <context:component-scan base-package="trial" /> </beans> |
- The tag ‘context:annotation-config‘ tells spring to go the annotation way.
- The tag ‘context:component-scan‘ tells spring to look for annotated classes in the specified package. Once you put this tag you do not need the ‘context:annotation-config’ tag.
- Sometimes when we auto wire by type there may be multiple beans of the same type (or inherited type). One case is if you define multiple datsasources. How do you tell your bean in that case which one to pick. In this case use @Qualifier(“beanid”) to select the specific one.
Now to test this, lets write up a quick JUnit unit test using support from Spring TextContext Framework. To quote directly from the Spring documentation:
“The Spring TestContext Framework (located in the org.springframework.test.context package) provides generic, annotation-driven unit and integration testing support that is agnostic of the testing framework in use, for example JUnit 3.8, JUnit 4.4, TestNG 5.5, etc.”
The code is show below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package trial; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:context.xml" }) public class GreeterTestCase { @Autowired private Greeter greeter; @Test public void testGreeting() { System.out.println(greeter.getGreeting()); } } |
@RunWith – tells spring to use its test wrapper to run the junit4 test case.
Once you execute this test you will see something like:
>> Good day. The time is now Thu Mar 13 21:20:30 EDT 2008
To get you in a more lively mood…no its not alcohol…there is also a @Aspect and @Pointcut tags which let you configure AOP related items.
More Annotations:
- You can use @Repository to instead of @Service to mark DAO implementations.
- @Component is a generic annotation to mark any object as a spring managed object. @Repository and @Service are special stereotypes that mark business service and DAO classes.
- @Required is used to mark a property as required to be set. At runtime an IllegalArgumentException will be thrown if this dependency is not wired.
- @Transactional is used to mark methods/classes as transactional. If applied on the class it applies to all methods otherwise to specific methods. For this to work you must set up a transaction manager and also enable annotation driven transaction demarcation using
1<span class="bold"><strong><tx:annotation-driven transaction-manager="txManager"/></strong></span> - You can also use the JSR-250 annotation @Resource(name=”abc”) to perform dependency injection. Name will be the id of the bean.
- Another pair of JSR-250 annotations that are supported are the lifecycle method annotations @PostConstruct and @PreDestroy. These will mark methods that need to be notified when those lifecycle events occur.