According to the Spring development team, the core theme of Spring 2.5 that was released in October 2007 is to provide comprehensive support for configuration annotations in application components. Annotation support was first announced in Spring 2.0, and has been significantly enhanced in Spring 2.5. It introduces support for a complete set of configuration annotations.
I'll briefly discuss the annotation-driven configuration and auto-detection support in Spring 2.5 with the help of a simple tutorial.
What you need before you start
You need the following software to try out the tutorial.
You also need the following jars in your classpath. These are available with the Spring distribution.
spring.jar
asm-2.2.3.jar
asm-commons-2.2.3.jar
aspectjweaver.jar
aspectjrt.jar
hsqldb.jar
commons-logging.jar
log4j-1.2.14.jar
junit-4.4.jar
spring-test.jar
common-annotations.jar(This is not required if Java 6.0 or later is used)
Adding the classes and interfaces for the example
The example is just a simple service that saved a new customer in database.
Table Customer:
CREATE TABLE `customer` (
`id` int(9) NOT NULL,
`lastname` varchar(64) NOT NULL DEFAULT '',
`firstname` varchar(64) DEFAULT NULL,
`address` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
package org.domain.entites;
/**
* @author wassim
*
*/
public class Customer {
private int id;
private String firstname;
private String lastname;
private String address;
//getter and setter Methods for all attributes
}
Let me start with the CustomerService interface.
package org.domain.services; public interface CustomerService {
public void saveCustomer(Customer customer);
}
Here is a simple class that implements this interface.
@Service
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerDao customerDao;
public void saveCustomer(Customer customer) {
customerDao.saveCustomer(customer);
}
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
}
Stereotype Annotations
Classes marked with stereotype annotations are candidates for auto-detection by Spring when using annotation-based configuration and classpath scanning. The @Component annotation is the main stereotype that indicates that an annotated class is a "component".
The @Service stereotype annotation used to decorate the EmployeeServiceImpl class is a specialized form of the @Component annotation. It is appropriate to annotate the service-layer classes with @Service to facilitate processing by tools or anticipating any future service-specific capabilities that may be added to this annotation.
The @Repository annotation is yet another stereotype that was introduced in Spring 2.0 itself. This annotation is used to indicate that a class functions as a repository (the CustomerDAOImpl below demonstrates the use) and needs to have exception translation applied transparently on it. The benefit of exception translation is that the service layer only has to deal with exceptions from Spring's DataAccessException hierarchy, even when using plain JPA in the DAO classes.
@autowired
Another annotation used in CustomerServiceImpl is @autowired . This is used to autowire the dependency of the CustomerServiceImpl on the CustomerDao . Here is the CustomerDao interface.
public interface CustomerDao { public void saveCustomer(Customer customer); }
The implementing class EmployeeDaoImpl uses the @Repository annotation.
@Repository
public class CustomerDaoImpl implements CustomerDao {
@Autowired
private SimpleJdbcTemplate simplejdbcTemplate;
public void saveCustomer(Customer customer) {
String sql=”insert into Customer(id,firstname,lastname,address) ”+ “ values(?,?,?,?)”;
this.simplejdbcTemplate.update(sql,customer.getId(),customer.getFirstname(),customer.getLastname(),customer.getAddress());
}
}
Here again, the DataSource implementation is autowired to the argument taken by the method that creates the SimpleJdbcTemplate object.
Simplified Configuration
The components discovered by classpath scanning are turned into Spring bean definitions, not requiring explicit configuration for each such bean. So the Spring configuration xml file is very simple
Now let me explain the new configurations in the above Spring context file. The
The properties for the data source are taken from the jdbc.properties file in the classpath. The property placeholders are configured with the
The
@Aspect
The @Aspect annotation on a class marks it as an aspect along with @Pointcut definitions and advice (@Before, @After, @Around) as demonstrated in the TraceLogger class defintion below. The PointCut is applied for all methods in the EmployeeServiceImpl class. The @Before annotation indicates that the log() method in the TraceLogger is to be invoked by Spring AOP prior to calling any method in EmployeeServiceImpl.
@Component
@Aspect
public class TraceLogger {
private static final Logger LOG = Logger.getLogger(TraceLogger.class);
@Pointcut("execution(* org.domain.services.EmployeeServiceImpl.*(..))")
public void empTrace() {
} @Before("empTrace()")
public void log(JoinPoint joinPoint) {
LOG.info("Before calling " + joinPoint.getSignature().getName()
+ " with argument " + joinPoint.getArgs()[0]);
}
}
Since there is no definition provided for TraceLogger in the Spring context file, it is marked for auto-detection from the classpath using the @Component annotation.
@Qualifier and @Resource
Suppose there is one more DataSource configuration in the spring context file as follows.
class="org.springframework.jndi.JndiObjectFactoryBean">
Since auto-detection is enabled, auto-wiring will fail since both data source beans are equally eligible candidates for wiring. It is possible to achieve by-name auto-wiring by providing a bean name within the @Qualifier annotation as follows. The below method injects the DataSource implementation by specifying the name dataSource�.
@Autowired public void createTemplate(@Qualifier("dataSource") DataSource dataSource) {
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource); }
JSR-250 Annotations
Spring also provides support for Java EE 5 Common Annotations (JSR-250). The supported annotations are @Resource, @PostConstruct and @PreDestroy. The @Resource annotation is also supported by Spring for autowiring as shown in the below code, the bean name to be autowired is passed.
@Resource(name = "dataSource")
public void createTemplate(DataSource dataSource)
{
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
The JSR-250 lifecycle annotations @PostConstruct and @PreDestroy can be used to specify initialization callbacks and destruction callbacks respectively. To demonstrate the use of these, I’m adding the following code to the CustomerDaoImpl class.
@PostConstruct public void initialize() {
jdbcTemplate.update("CREATE TABLE `customer` (
id int(9) NOT NULL PRIMARY KEY,
lastname varchar(64) NOT NULL DEFAULT '',
firstname varchar(64) DEFAULT NULL,
address varchar(128) DEFAULT NULL,
) “) }
@PreDestroy
public void remove() {
jdbcTemplate.update("drop table customer");
}
Unit Testing
Before testing the service implementation, I provided the database configuration details in the jdbc.properties file as follows.
jdbc.driver=org.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/blog
jdbc.username=root
jdbc.password=youpassword
Here is the class I wrote for unit testing.
public class CustomerServiceImplTests extends AbstractDependencyInjectionSpringContextTests {
@Autowired
private CustomerService customerService;
@Override
protected String[] getConfigLocations() {
return new String[] { "applicationContext.xml" };
Customer customer=new Customer();
customer.setId(1);
customer.setFirstname('Test');
customer.setLastname('Test');
customer.setAddress('Test');
customerService.saveCustomer(customer);
}
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
}

Aucun commentaire:
Enregistrer un commentaire