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:
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:
Classe com o método mainFiz 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:
Bom, pessoal, vou ficando por aqui e espero que tenham gostado!
Abraços!