La programmation par AOP permet de dissocier le code technique du code fonctionnel.
Cela permet ainsi d'isoler les problème de framework, de séparer les couches et surtout de fournir au développeur un cadre de travail orienté fonctionnel.
Nous utiliserons Spring AOP, qui est une implémentation de la librairie AspectJ via Spring pour une prise en main rapide. Cette librairie utilise le mechanisme de proxy de classe Java tel explicité dans la doc:
http://static.springsource.org/spring/docs/2.0.x/reference/aop.html
Sa particularité est de n'être utilisable que sous certaines conditions :
La classe cible du greffon doit :
- Etre déclaré comme un bean au niveau de spring ( cf applicationContext.xml)
- Posséder des méthodes publiques et non statiques( les méthodes statiques ne peuvent avoir de greffon)
- Etre instanciée via le mechanisme de d'injection de dépendance spring.
Voici donc un exemple de projet Spring AOP qui marche :
Dans le pom.xml, les dépendences à inclure : :
<dependencies>
<dependency> <groupId>org.springframework.ws</groupId> <artifactId>spring-oxm</artifactId> <version>1.5.7</version> </dependency> <dependency> <groupId>org.springframework.ws</groupId> <artifactId>spring-ws-core</artifactId>
<version>1.5.7</version> </dependency>
<dependency> <groupId>junit</groupId>
<artifactId>junit</artifactId> <version>3.8.1</version>
<scope>test</scope> </dependency>
<dependency>
<groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>2.5.1</version> </dependency>
<dependency>
<groupId>aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.2</version>
</dependency> <dependency>
<groupId>aspectj</groupId> <artifactId>aspectjweaver</artifactId>
<version>1.5.2</version>
</dependency> <dependency> <groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId> <version>2.1_3</version>
</dependency>
</dependencies>
<?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" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy /> <!-- il faut declarer les beans que spring doit renseigner --> <bean id="monAspect" class="com.bsf.MonAspect"></bean> <bean id="monService" class="com.bsf.ServiceT"></bean> <aop:config></aop:config>
</beans>
package com.bsf; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut;Enfin la classe ServiceT :
@Aspect public class MonAspect { public MonAspect(){ super(); } @After("execution(* com.bsf.ServiceT.*(..))") public void moiAfter(){ System.out.println("Aspect:sur ServiceT.moi():moiAfter "); } }
package com.bsf; public class ServiceT { public void moi(){ System.out.println("ServiceT.moi()"); } public void moiAvecParams(String param) { System.out.println("ServiceT.moiAvecParams(" + param + ")"); } }
package com.bsf; import junit.framework.TestCase; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AspectTest extends TestCase { public void testService() { ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" }); System.out.println(" debut test service "); ServiceT st = (ServiceT) context.getBean("monService"); st.moi(); st.moiAvecParams("ok"); System.out.println(" fin service"); } }