Introdução aos tipos de conselhos na primavera

Introdução aos tipos de conselhos na primavera

1. Visão geral

Neste artigo, discutiremos diferentes tipos de conselhos de AOP que podem ser criados no Spring.

Advice é uma ação realizada por um aspecto em um ponto de junção específico. Diferentes tipos de aconselhamento incluem conselhos "por perto", "antes" e "depois". O principal objetivo dos aspectos é apoiar preocupações transversais, como criação de log, criação de perfil, armazenamento em cache e gerenciamento de transações.

E se você quiser se aprofundar nas expressões de pointcut, verifiqueyesterdays intro to these.

2. Conselhos de habilitação

Com o Spring, você pode declarar conselhos usando anotações AspectJ, mas você deve primeiro aplicar a anotação@EnableAspectJAutoProxy à sua classe de configuração, o que permitirá o suporte para manipulação de componentes marcados com a anotação@Aspect de AspectJ.

@Configuration
@ComponentScan(basePackages = {"org.example.dao", "org.example.aop"})
@EnableAspectJAutoProxy
public class TestConfig {
    ...
}

3. Antes do Conselho

Este conselho, como o nome indica, é executado antes do ponto de junção. Não impede a execução continuada do método recomendado, a menos que uma exceção seja lançada.

Considere o seguinte aspecto que simplesmente registra o nome do método antes de ser chamado:

@Component
@Aspect
public class LoggingAspect {

    private Logger logger = Logger.getLogger(LoggingAspect.class.getName());

    @Pointcut("@target(org.springframework.stereotype.Repository)")
    public void repositoryMethods() {};

    @Before("repositoryMethods()")
    public void logMethodCall(JoinPoint jp) {
        String methodName = jp.getSignature().getName();
        logger.info("Before " + methodName);
    }
}

O conselhologMethodCall será executado antes de qualquer método de repositório definido pelo pointcutrepositoryMethods.

4. Depois do Conselho

Após o conselho, declarado usando a anotação@After, __ é executado após a execução de um método correspondente, independentemente de uma exceção ter sido lançada ou não.

Em alguns aspectos, é semelhante a um blocofinally. No caso de você precisar que o conselho seja acionado somente após a execução normal, você deve usar oreturning advice declarado pela anotação@AfterReturning. Se você deseja que seu conselho seja acionado apenas quando o método de destino lançar uma exceção, você deve usarthrowing advice, declarado usando a anotação@AfterThrowing.

Suponha que desejamos notificar alguns componentes do aplicativo quando uma nova instância deFoo é criada. Poderíamos publicar um evento deFooDao, mas isso violaria o princípio de responsabilidade única. Em vez disso, podemos fazer isso definindo o seguinte aspecto:

@Component
@Aspect
public class PublishingAspect {

    private ApplicationEventPublisher eventPublisher;

    @Autowired
    public void setEventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    @Pointcut("@target(org.springframework.stereotype.Repository)")
    public void repositoryMethods() {}

    @Pointcut("execution(* *..create*(Long,..))")
    public void firstLongParamMethods() {}

    @Pointcut("repositoryMethods() && firstLongParamMethods()")
    public void entityCreationMethods() {}

    @AfterReturning(value = "entityCreationMethods()", returning = "entity")
    public void logMethodCall(JoinPoint jp, Object entity) throws Throwable {
        eventPublisher.publishEvent(new FooCreationEvent(entity));
    }
}

Observe, primeiro, que usando a anotação@AfterReturning, podemos acessar o valor de retorno do método de destino. Em segundo lugar, ao declarar um parâmetro do tipoJoinPoint,, podemos acessar os argumentos da invocação do método de destino.

Em seguida, criamos um ouvinte que simplesmente registrará o evento. Você pode ler mais sobre eventos emthis tutorial:

@Component
public class FooCreationEventListener implements ApplicationListener {

    private Logger logger = Logger.getLogger(getClass().getName());

    @Override
    public void onApplicationEvent(FooCreationEvent event) {
        logger.info("Created foo instance: " + event.getSource().toString());
    }
}

5. Cerca de conselhos

Around advice envolve um ponto de junção, como uma chamada de método.

Este é o tipo mais poderoso de conselho. O conselho alternativo pode executar um comportamento personalizado antes e depois da chamada do método. Também é responsável por escolher se deseja prosseguir para o ponto de junção ou atalho para a execução do método recomendado, fornecendo seu próprio valor de retorno ou lançando uma exceção.

Para demonstrar seu uso, suponha que você queira medir o tempo de execução do método. Para esse fim, você pode criar o seguinte aspecto:

@Aspect
@Component
public class PerformanceAspect {

    private Logger logger = Logger.getLogger(getClass().getName());

    @Pointcut("within(@org.springframework.stereotype.Repository *)")
    public void repositoryClassMethods() {};

    @Around("repositoryClassMethods()")
    public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.nanoTime();
        Object retval = pjp.proceed();
        long end = System.nanoTime();
        String methodName = pjp.getSignature().getName();
        logger.info("Execution of " + methodName + " took " +
          TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
        return retval;
    }
}

Este conselho é acionado quando qualquer um dos pontos de junção correspondidos pelo corte de pontorepositoryClassMethods é executado.

Este conselho usa um parâmetro do tipoProceedingJointPoint. O parâmetro nos dá a oportunidade de executar uma ação antes da chamada do método de destino. Nesse caso, simplesmente salvamos a hora de início do método.

Em segundo lugar, o tipo de retorno de conselho éObject, pois o método de destino pode retornar um resultado de qualquer tipo. Se o método de destino forvoid,,null será retornado. Após a chamada do método de destino, podemos medir o tempo, registrá-lo e retornar o valor do resultado do método para o chamador.

6. Visão geral

Neste artigo, aprendemos os diferentes tipos de conselhos no Spring e suas declarações e implementações. Definimos aspectos usando abordagem baseada em esquema e usando anotações AspectJ. Também fornecemos várias aplicações de aconselhamento possíveis.

A implementação de todos esses exemplos e fragmentos de código pode ser encontrada emmy github project - este é um projeto baseado em Eclipse, portanto, deve ser fácil de importar e executar como está.