Una volta definiti gli advice, non ci resta per associare gli advice creati ad un target object, che, nel nostro caso, è rappresentato dall'implementazione dell'interfaccia BookDao
. Lo facciamo modificando la configurazione dello IoC Container
Riprendendo il file di configurazione utilizzato nell'esempio sull'accesso ai dati tramire JDBC, andiamo ad aggiungere la definizione dei bean necessari all'utilizzo di AOP.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver" />
<property name="url" value="jdbc:derby://localhost:1527/library;create=true" />
<property name="username" value="app" />
<property name="password" value="app" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="bookDao" class="it.html.spring.book.BookSimpleJdbcDaoSupportNamedValue">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- Proxy verso il target object -->
<bean id="bookDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>it.html.spring.book.BookDao</value>
</list>
</property>
<property name="target" ref="bookDao" />
<property name="interceptorNames">
<list>
<value>logBeforeAdvice</value>
<value>logAfterReturningAdvice</value>
<value>logThrowAdvice</value>
<!-- Per utilizzare l'Around Advice decommentare la riga sottostante e commentare i tre advice soprastanti -->
<!-- <value>logAroundAdvice</value> -->
</list>
</property>
</bean>
<!-- Definizione degli advice -->
<bean id="logBeforeAdvice" class="it.html.spring.aop.classic.LogBeforeAdvice" />
<bean id="logAfterReturningAdvice" class="it.html.spring.aop.classic.LogAfterReturningAdvice" />
<bean id="logThrowAdvice" class="it.html.spring.aop.classic.LogThrowAdvice" />
<bean id="logAroundAdvice" class="it.html.spring.aop.classic.LogAroundAdvice" />
</beans>
Perché sia possibile intercettare i metodi di un target object è necessario wrapparlo in una classe proxy. Nella configurazione presa in esame il target object è rappresentato dal bean BookDao
wrappato per mezzo del bean bookDaoProxy
istanza della classe org.springframework.aop.framework.ProxyFactoryBean
.
Al bookDaoProxy
è stata poi associata tramite la proprietà interceptorNames
la lista degli advice da utilizzare sul taget object.
Lanciamo il test
Concludiamo il nostro primo esperimento con Spring AOP, scrivendo una classe per testare i risultati ottenuti. Se tutto è andato bene, dovremmo vedere una riga di output per ogni invocazione di metodo, contenente i dettagli dell'invocazione stessa e le eventuali eccezioni ottenute.
public class BookClient {
public static void main(String[] args) {
BeanFactory ctx = new XmlBeanFactory(new ClassPathResource("beans.xml"));
BookDao bookDao = (BookDao) ctx.getBean("bookDaoProxy");
// Delete
bookDao.delete("1234567890123");
bookDao.delete("1234567890321");
// Insert Promessi Sposi
Book book = new Book();
book.setIsbn("1234567890123");
book.setAuthor("Manzoni");
book.setTitle("I Promessi Sposi");
bookDao.insert(book);
// Insert Il Barone Rampante
book = new Book();
book.setIsbn("1234567890321");
book.setAuthor("Italo Calvino");
book.setTitle("Il Barone Rampante");
bookDao.insert(book);
// Find Promessi Sposi
book = bookDao.findByISBN("1234567890123");
// Update Promessi Sposi
book.setAuthor("Alessandro Manzoni");
bookDao.update(book);
// Book Count
bookDao.bookCount();
// Find all books
bookDao.findAllBooks();
}
}
Per effettuare delle prove è possibile scaricare l'esempio completo.