English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Exemplo de anotação do Spring AOP AspectJ

Framework SpringRecomendamos que você use o Spring 1.2Usado no AOP antigo estilo dtd Implementação do Spring AspectJ AOPFácil de usar.

Existem duas maneiras de usar a implementação do Spring AOP AspectJ:

Através de comentários: Vamos aprender isso aqui. Através da configuração xml (baseada no padrão): Vamos aprender isso na próxima página.

Atenção: Para entender o conceito de aop e suas vantagens, acesse aqui. Tutorial de conceito de aop

A implementação do Spring AspectJ AOP oferece muitos comentários:

@Aspect Declarou a classe como aspecto. @Pointcut Declarou expressão de ponto de interrupção.

Os comentários usados para criar sugestões são os seguintes:

@Before Declarou sugestão before. É aplicada antes da chamada do método real. @After Declarou sugestão after. É aplicada após a chamada do método real e antes de retornar o valor. @AfterReturning Declarou sugestão de retorno após. É aplicada após a chamada do método real e antes de retornar o valor. Mas você pode obter o valor de retorno na sugestão. @Around Declarou sugestão de envolvente. É aplicada antes e após a chamada do método real. @AfterThrowing Declarou sugestão throws. Se o método real lançar uma exceção, aplicará este método.

Entendendo a expressão de ponto de interrupção

A expressão de ponto de interrupção é uma linguagem de expressão do Spring AOP.

@Pointcut Os comentários são usados para definir pontos de interrupção. Também podemos referenciar expressões de pontos de interrupção por nome. Vamos ver um exemplo simples de expressão de ponto de interrupção.

@Pointcut("execution(")* Operação.*(..))
private void doSomething() {}

O nome da expressão de ponto de interrupção é doSomething(). independentemente do tipo de retorno, será aplicada a todos os métodos da classe Operation.

Entendendo a expressão de ponto de interrupção

Vamos tentar entender a expressão de ponto de interrupção através do seguinte exemplo:

@Pointcut("execution(public * *(..))

Será aplicado a todos os métodos públicos.


@Pointcut("execution(public Operation.*(..))

Será aplicado a todos os métodos públicos da classe Operation.


@Pointcut("execution(")* Operação.*(..))

Será aplicado a todos os métodos da classe Operation.


@Pointcut("execution(public Employee.set*(..))

Será aplicado a todos os métodos públicos da classe Employee.


@Pointcut("execution(int Operation.*(..))

Será aplicado a todos os métodos da classe Operation que retornam int.


1、@Before exemplo

Apply AspectJ Before Advice before the actual business logic method. You can perform any operation here, such as conversion, authentication, etc.

Crie uma classe que contenha a lógica de negócios real.

Arquivo: Operation.java

package com.w;3codebox;
public class Operation{
	public void msg(){System.out.println("msg method invoked");}
	public int m(){System.out.println("m method invoked");return 2;}
	public int k(){System.out.println("k method invoked");return 3;}
}

Agora, crie a classe aspect que contém a sugestão antes.

Arquivo: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation{
	@Pointcut("execution(")* Operação.*(..))
	public void k(){}//nome do pointcut
	@Before("k()")//Apply the pointcut on the before notification
	public void myadvice(JoinPoint jp)//it is advice (before advice)
	{
		System.out.println("concern adicional");
		//System.out.println("Assinatura do método: "}  + jp.getSignature());
	}
}

Agora, crie o arquivo applicationContext.xml que define o bean.

Arquivo: applicationContext.xml

<?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.xsd 
	   http://www.springframework.org/schema/aop 
	   http://www.springframework.org/schema/aop/spring-aop.xsd">
	<bean id="opBean" class="com.w3codebox.Operation">	</bean>
	<bean id="trackMyBean" class="com.w3codebox.TrackOperation"></bean>
	<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
</beans>

Agora, chamemos o método real.

Arquivo: Test.java

package com.w;3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation e = (Operation) context.getBean("opBean");
		System.out.println("chamando msg...");
		e.msg();
		System.out.println("chamando m...");
		e.m();
		System.out.println("chamando k...");
		e.k();
	}
}

Saída

chamando msg...
concern adicional
msg() method invoked
chamando m...
concern adicional
método m() invocado
chamando k...
concern adicional
método k() invocado

Como você pode ver, antes da chamada dos métodos msg(), m() e k(), também aparecerão outros problemas.

Agora, se você alterar a expressão do pointcut conforme mostrado:

@Pointcut("execution(")* Operation.m*(..))

Agora, vamos nos concentrar mais nos métodos começando com m na classe Operation. A saída será como a seguir:

chamando msg...
concern adicional
msg() method invoked
chamando m...
concern adicional
método m() invocado
chamando k...
método k() invocado

Agora você pode ver que antes da chamada do método k() não foi impresso nenhum outro problema.


2Exemplo de @After

Após a chamada da lógica de negócio real, aplica-se o AspectJ após a sugestão after. Ele pode ser usado para manter logs, segurança, notificações, etc.

Aqui, supomos Operation.java applicationContext.xml e Test.java O arquivo é o mesmo que o fornecido no exemplo @Before.

Arquivo: TrackOperation.Java
package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation{
	@Pointcut("execution(")* Operação.*(..))
	public void k(){}//nome do pointcut
	@After("k()")//aplicando o pointcut no aspecto após a sugestão
	public void myadvice(JoinPoint jp)//it is advice (after advice)
	{
		System.out.println("concern adicional");
		//System.out.println("Assinatura do método: "}  + jp.getSignature());
	}
}
 

Saída

chamando msg...
msg() method invoked
concern adicional
chamando m...
método m() invocado
concern adicional
chamando k...
método k() invocado
concern adicional
 

Você pode ver que após a chamada dos métodos msg(), m() e k(), também aparecerão outros problemas.


3Exemplo de @AfterReturning

Ao usar a sugestão de retorno após o retorno, podemos obter o resultado na sugestão.

Criar a lógica de negócio da classe que contém o seguinte conteúdo.

Arquivo: Operation.java

package com.w;3codebox;
public class Operation{
	public int m(){System.out.println("m() method invoked");return 2;}
	public int k(){System.out.println("k() method invoked");return 3;}
}
 

Criar a classe de aspecto que contém a sugestão de retorno.

Arquivo: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
	@AfterReturning(
		      pointcut = "execution(* Operação.*(..))",
		      returning = "result")
		      
	public void myadvice(JoinPoint jp, Object result)//it is advice (after returning advice)
	{
		System.out.println("concern adicional");
		System.out.println("Assinatura do método: "}  + jp.getSignature());
		System.out.println("Result in advice: ")+result);
		System.out.println("fim do conselho de after returning...");
	}
}
 

Arquivo: applicationContext.xml

com o exemplo dado no @Before sugestão

Arquivo: Test.java

Agora, crie a classe Test para chamar o método real.

package com.w;3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation e = (Operation) context.getBean("opBean");
		System.out.println("chamando m...");
		System.out.println(e.m());
		System.out.println("chamando k...");
		System.out.println(e.k());
	}
}
 

Saída

chamando m...
método m() invocado
concern adicional
Assinatura do método: int com.w3codebox.Operation.m()
Resultado do conselho: 2
fim do conselho de after returning...
2
chamando k...
método k() invocado
concern adicional
Assinatura do método: int com.w3codebox.Operation.k()
Resultado do conselho: 3
fim do conselho de after returning...
3
 

Você pode ver que o valor de retorno foi impresso duas vezes, uma vez pela classe TrackOperation e outra pela classe Test.


4, exemplo @Around

O AspectJ ao redor da notificação é aplicado antes e após a chamada do método de lógica de negócios real.

Aqui, estamos supondo   applicationContext.xml O arquivo é o mesmo que o fornecido no exemplo @Before.

Crie uma classe que contenha a lógica de negócios real.

Arquivo: Operation.java

package com.w;3codebox;
public class Operation{
	public void msg(){System.out.println("msg() foi invocado");}
	public void display(){System.out.println("display() foi invocado");}
}
 

Crie uma classe que contenha o aspecto ao redor do conselho.

Você precisa passar no método advice   PreceedingJoinPoint referência, para que possamos chamar o método request() através de chamadas proce.

Arquivo: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation
{
	@Pointcut("execution(")* Operação.*(..))
	public void abcPointcut(){}
	@Around("abcPointcut()")
	public Object myadvice(ProceedingJoinPoint pjp) throws Throwable 
	{
		System.out.println("Pr concerns antes de chamar o método real");
		Object obj=pjp.proceed();
		System.out.println("Pr concerns após a chamada do método real");
		return obj;
	}
}
 

Arquivo: Test.java

Agora, crie a classe Test para chamar o método real.

package com.w;3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new classPathXmlApplicationContext("applicationContext.xml");
		Operation op = (Operation) context.getBean("opBean");
		op.msg();
		op.display();
	}
}
 

Saída

Pr concerns antes de chamar o método real
msg() é invocado
Pr concerns após a chamada do método real
Pr concerns antes de chamar o método real
display() é invocado
Pr concerns após a chamada do método real
 

Você pode ver que antes e depois de chamar o método msg() e mostrar, também são impressas outras questões.


5Exemplo de @AfterThrowing

Usando a sugestão after throw, podemos imprimir a exceção na classe TrackOperation. Vamos ver um exemplo de sugestão AspectJ AfterThrowing.

Criar uma classe que contém lógica de negócios.

Arquivo: Operation.java

package com.w;3codebox;
public class Operation{
	public void validate(int age) throws Exception{
	if(age<18){
		throw new ArithmeticException("Idade não válida");
	}
	else{
		System.out.println("Agradecemos pelo voto");
	}
	}
}
 

Crie uma classe de aspecto que contém a lógica após o conselho ser lançado.

Aqui, precisamos passar uma referência de Throwable para que possamos interceptar a exceção aqui.

Arquivo: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
	@AfterThrowing(
		      pointcut = "execution(* Operação.*(..))",
		      throwing = "error")
		      
	public void myadvice(JoinPoint jp, Throwable error)//é conselho
	{
		System.out.println("concern adicional");
		System.out.println("Assinatura do método: "}  + jp.getSignature());
		System.out.println("A exceção é: "}+error);
		System.out.println("fim de after throwing advice...");
	}
}
 

Arquivo: applicationContext.xml

com o exemplo dado no @Before sugestão

Arquivo: Test.java

Agora, crie a classe Test para chamar o método real.

package com.w;3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation op = (Operation) context.getBean("opBean");
		System.out.println("chamando validate...");
		try{
			op.validate(19);
		}catch(Exception e){System.out.println(e);}
		System.out.println("chamando validate novamente...");
		try{
		    op.validate(11);
		}catch(Exception e){System.out.println(e);}
	}
}
 

Saída

chamando validate...
Obrigado pelo voto
chamando validate novamente...
concern adicional
Assinatura do método: void com.w3codebox.Operation.validate(int)
Exceção é: java.lang.ArithmeticException: Idade não válida
fim do after throwing advice...
java.lang.ArithmeticException: Idade não válida