Back-End

30 jul, 2013

Série Spring: Spring AOP com Annotations

Publicidade

Olá Pessoal,

No artigo de hoje vamos ver como usar annotations   para AOP. É bem simples! Já vimos aqui  com XML e agora vamos para o que há de melhor  desde do Java 5 que é o uso de Annotations.

Let’s go…

Starting

O artigo é bem curto e procurei  ser bem objetivo, então considerando que você já tem seu arquivo de Spring configurado para usar AOP, vamos apenas atualizar para habilitar o recurso de annotations  e aproveitei removi os beans  usando auto-discovering do Spring. Vamos começar pela configuração do arquivo springconfiguration.xml (o nome que dei ao meu arquivo de configuração).

Antes disso, crie um projeto novo e dê o nome que quiser.

Nota: lembre-se de adicionar os .jars do Spring, AOP e AspectJ ao projeto:

springaopannotationsproject_01

Configurando .xml do Spring

[java] <beans xmlns=<i>“http://www.springframework.org/schema/beans”</i>
xmlns:xsi=<i>“http://www.w3.org/2001/XMLSchema-instance”</i>
xmlns:context=<i>“http://www.springframework.org/schema/context”</i>
xmlns:aop=<i>“http://www.springframework.org/schema/aop”</i>
xsi:schemaLocation=<i>“http://www.springframework.org/schema/beans</i>
<i>http://www.springframework.org/schema/beans/spring-beans-3.2.xsd</i>
<i>http://www.springframework.org/schema/aop</i>
<i>http://www.springframework.org/schema/aop/spring-aop-3.2.xsd</i>
<i>http://www.springframework.org/schema/context</i>
<i>http://www.springframework.org/schema/context/spring-context-3.2.xsd”</i>>
<context:component-scan base-package=<i>“*”</i>/>
<aop:aspectj-autoproxy/>
</beans>[/java]

Deixe seu arquivo de configuração assim. A única coisa nova de aop foi adicionar a linha <aop:aspectj-autorproxy/>  que nos permite usar annotations.

Criando o bean

A seguir vamos criar o bean, nada demais neles:

[java]</pre>
@Component

@Scope(value=”prototype”)

public class Student {

private String name;

// this is DI via annotations

@Autowired

private Course course;

public String getName() {

return name;

}

public void setName(String name) {

if (name==null) {

throw new IllegalArgumentException();

}

this.name = name;

}

public Course getCourse() {

return course;

}

public void setCourse(Course course) {

this.course = course;

}

public void teste(){

}
} [/java]

O outro bean:

[java]

@Component

<b>public</b> <b>class</b> Course {

<b>private</b> String nameCourse;

<b>public</b> String getNameCourse() {

<b>return</b> nameCourse;

}

<b>public</b> <b>void</b> setNameCourse(String nameCourse) {

<b>this</b>.nameCourse = nameCourse;

}

} [/java]

Agora vamos criar uma classe que será responsável por registrar uma mensagem antes;após de determinados métodos, ou seja, as regras do AOP estarão aqui:

[java]

@Aspect

@Component

<b>public</b> <b>class</b> Audit {

//    aqui com o metodo especifico

@Pointcut(“execution(* br.com.camilolopes.bean.Student.setName(..))”)

<b>public</b> <b>void</b> aopteste(){}

@Pointcut(“execution(* br.com.camilolopes.bean.Course.setNameCourse(..))”)

<b>public</b> <b>void</b> aopcourse(){}

@Pointcut(“execution(* *.*test*(..))”)

<b>public</b> <b>void</b> aopanywhere(){}

@AfterReturning(“aopteste()”)

<b>public</b> <b>void</b> register(){

System.<i>out</i>.println(“Student registred”);

}

@After(“aopcourse()”)

<b>public</b> <b>void</b> finished(){

System.<i>out</i>.println(“Course finished”);

}

@AfterThrowing(“aopteste()”)

<b>public</b> <b>void</b> problem(){

System.<i>out</i>.println(“Happened problem here”);

}

@Before(“aopteste()”)

<b>public</b> <b>void</b> starting(){

System.<i>out</i>.println(“application is starting…”);

}

@AfterReturning(“aopanywhere()”)

<b>public</b> <b>void</b> anywhere(){

System.<i>out</i>.println(“anywhere test”);

}

} [/java]

Observe que anotei a classe com @Component para que o Spring saiba que precisa registrar ela no contexto. Caso contrário, nada rola. Agora vamos entender os pointcuts criados:

  • Primeiro: criamos um pointcut que sempre será chamado quando um método especifico for chamado nesse caso o método  setName da classe Student.
  • Segundo: o mesmo que acima, exceto que para a classe Course.
  • Terceiro:  agora criamos um que estou dizendo “de qualquer lugar da aplicação e qualquer método que comece com test e terminar com qualquer coisa.

E  os métodos a seguir é o que serão chamados com base no que tipo de anotação que definimos. Observe que temos um que será chamado apenas no caso de acontecer uma exceção quando no método setName da classe Student.

Testando

Para testar aplicação criei uma classe de teste

Classe de Test

[java]

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations={“classpath:config/springconfiguration.xml”})

public class StudentTest {

@Autowired

private Student student;

@Before

public void setUp() throws Exception {

}

@Test

public void testNameCourse() {

student.getCourse().setNameCourse(“TDD”);

assertEquals(“TDD”,student.getCourse().getNameCourse());

}

@Test

public void testNameStudent(){

student.setName(“Camilo”);

assertEquals(“Camilo”, student.getName());

student.teste();

}

@Test(expected=IllegalArgumentException.class)

public void testNameIsNullException(){

student.setName(null);

}

} [/java]

Resultado:

resultaopunittest_02

Classe com o método main

Fiz uma pequena classe com método main, para quem não sabe unit test:

[java]

public class MainTest {

public static void main(String[] args) {

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“config/springconfiguration.xml”);

Student bean = (Student) applicationContext.getBean(“student”);

bean.setName(“lopes”);

bean.teste();

}

} [/java]

O resultado será diferente porque as inovações são diferentes:

resultadoaopmaintest_03

Bom, pessoal, vou ficando por aqui e espero que tenham gostado!

Abraços!