Olá Pessoal,
No post 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.
Lets go…
Starting
O post é 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.
Note: lembre-se de adicionar os .jars do Spring, AOP e AspectJ ao projeto:
Configurando .xml do Spring
<beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xmlns:context=“http://www.springframework.org/schema/context”
xmlns:aop=“http://www.springframework.org/schema/aop”
xsi:schemaLocation=“http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd”>
<context:component-scan base-package=“*”/>
<aop:aspectj-autoproxy/>
</beans>
Deixei seu arquivo de configuração assim. A única coisa nova de aop, foi que adicionar a linha <aop:aspectj-autorproxy/> que nos permite usar annotations.
Criando o bean
A seguir vamos criar o bean , nada demais neles:
@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(){
}
}
O outro bean:
@Component
public class Course {
private String nameCourse;
public String getNameCourse() {
return nameCourse;
}
public void setNameCourse(String nameCourse) {
this.nameCourse = nameCourse;
}
}
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:
@Aspect
@Component
public class Audit {
// aqui com o metodo especifico
@Pointcut(“execution(* br.com.camilolopes.bean.Student.setName(..))”)
public void aopteste(){}
@Pointcut(“execution(* br.com.camilolopes.bean.Course.setNameCourse(..))”)
public void aopcourse(){}
@Pointcut(“execution(* *.*test*(..))”)
public void aopanywhere(){}
@AfterReturning(“aopteste()”)
public void register(){
System.out.println(“Student registred”);
}
@After(“aopcourse()”)
public void finished(){
System.out.println(“Course finished”);
}
@AfterThrowing(“aopteste()”)
public void problem(){
System.out.println(“Happened problem here”);
}
@Before(“aopteste()”)
public void starting(){
System.out.println(“application is starting…”);
}
@AfterReturning(“aopanywhere()”)
public void anywhere(){
System.out.println(“anywhere test”);
}
}
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
@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);
}
}
Resultado:
Classe com o método main
Fiz uma pequena classe com método main, para quem não sabe unit test:
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();
}
}
O resultado será diferente pq as inovações são diferentes:
Bom, pessoal. Vou ficando por aqui e espero que tenham gostado do post.
Abraços,
Olá Camilo, bom dia!!
Parabéns pelo seu blog, muito útil e proveitoso !!
Duvida: Imagina que tenhamos um método save( Object obj ), neste caso, como conseguimos recuperar o valor do parâmetro no aspectJ …
Abraços,
Felipe Mozena