Spring AOP: Qual é a diferença entre JoinPoint e PointCut?


88

Estou aprendendo conceitos de Programação Orientada a Aspectos e Spring AOP. Não estou conseguindo entender a diferença entre um Pointcut e um Joinpoint - os dois parecem ser iguais para mim. Um Pointcut é onde você aplica seus conselhos e um Joinpoint também é um lugar onde podemos aplicar nossos conselhos. Então qual é a diferença?

Um exemplo de um pointcut pode ser:

@Pointcut("execution(* * getName()")

O que pode ser um exemplo de um Joinpoint?

Respostas:


161

Ponto de junção: um ponto de junção é um ponto candidato na execução do programa do aplicativo onde um aspecto pode ser conectado. Esse ponto pode ser um método sendo chamado, uma exceção sendo lançada ou mesmo um campo sendo modificado. Estes são os pontos onde o código do seu aspecto pode ser inserido no fluxo normal do seu aplicativo para adicionar um novo comportamento.

Conselho: Este é um objeto que inclui invocações de API para os interesses de todo o sistema que representam a ação a ser executada em um ponto de junção especificado por um ponto.

Pointcut: Um pointcut define em quais pontos de junção o Conselho associado deve ser aplicado. O conselho pode ser aplicado em qualquer ponto de junção suportado pela estrutura AOP. Obviamente, você não deseja aplicar todos os seus aspectos em todos os pontos de junção possíveis. Os pontos de corte permitem que você especifique onde deseja que seus conselhos sejam aplicados. Freqüentemente, você especifica esses pontos de corte usando nomes de classe e método explícitos ou por meio de expressões regulares que definem padrões de nome de classe e método correspondentes. Algumas estruturas AOP permitem que você crie pontos de corte dinâmicos que determinam se deve aplicar conselhos com base nas decisões de tempo de execução, como o valor dos parâmetros do método.

A imagem a seguir pode ajudá-lo a entender Advice, PointCut, Joinpoints. insira a descrição da imagem aqui

Fonte

Explicação usando Analogia de Restaurante: Fonte de @Victor

Quando você vai a um restaurante, olha um menu e vê várias opções para escolher. Você pode pedir um ou mais de qualquer um dos itens do menu. Mas até que você realmente os peça, eles são apenas "oportunidades para jantar". Depois de fazer o pedido e o garçom trazê-lo à sua mesa, é uma refeição.

Joinpoints são opções no menu e Pointcuts são itens que você seleciona.

Um Joinpoint é uma oportunidade dentro do código para você aplicar um aspecto ... apenas uma oportunidade. Depois de aproveitar essa oportunidade e selecionar um ou mais Joinpoints e aplicar um aspecto a eles, você terá um Pointcut.

Wiki de origem :

Um ponto de junção é um ponto no fluxo de controle de um programa onde o fluxo de controle pode chegar por dois caminhos diferentes (IMO: é por isso que chamamos de joint).

O conselho descreve uma classe de funções que modificam outras funções

Um pointcut é um conjunto de pontos de junção.


3
Isso deve ser marcado como resposta correta. Apenas para adicionar mais informações, dê uma olhada na resposta de Cragi Walls ... coderanch.com/t/485525/Spring/Difference-Joint-Point-Point-Cut .
Victor

2
Direto ao ponto: Um pointcut define em que conselhos de joinpoints devem ser aplicados +1
Naman Gala

Apenas para confirmação, more Joinpoints and apply an aspect to them, you've got a Pointcut. aspecto para eles ou conselho para eles?
Asif Mushtaq,

@Premraj Então, de acordo com a sua analogia, o conselho será pedir a refeição. Estou certo?
Vishwas Atrey 01 de

A analogia do restaurante ajudou a esclarecer a confusão entre JoinPoints e pointcuts, obrigado!
SM

30

Para entender a diferença entre um ponto de junção e um ponto de corte, pense em pontos de corte como especificando as regras de tecelagem e os pontos de junção como situações que satisfazem essas regras.

No exemplo abaixo,

  @Pointcut("execution(* * getName()")  

Pointcut define regras dizendo, o conselho deve ser aplicado no método getName () presente em qualquer classe em qualquer pacote e os joinpoints serão uma lista de todos os métodos getName () presentes nas classes para que o conselho possa ser aplicado a esses métodos.

(No caso do Spring, a regra será aplicada apenas aos beans gerenciados e o conselho pode ser aplicado apenas aos métodos públicos).


1
"Pointcut define regras dizendo, o conselho deve ser aplicado no método getName () presente em qualquer classe em qualquer pacote e os joinpoints serão uma lista de todos os métodos getName () presentes nas classes para que o conselho possa ser aplicado nesses métodos." Sinto muito, mas isso está ficando mais confuso. Você pode me dar uma analogia em um cenário da vida do dia a dia do mundo real?
Saurabh Patil

28

JoinPoints: são basicamente locais na lógica de negócios real onde você deseja inserir algumas funcionalidades diversas que são necessárias, mas que não fazem parte da lógica de negócios real. Alguns exemplos de JoinPints ​​são: chamada de método, método que retorna normalmente, método que lança uma exceção, instanciar um objeto, referenciar um objeto, etc ...

Pointcuts: Pointcuts são algo como expressões regulares que são usadas para identificar joinpoints. Pontcuts são expressos usando "linguagem de expressão pointcut". Pontos de corte são pontos de fluxo de execução onde a preocupação transversal precisa ser aplicada. Há uma diferença entre Joinpoint e Pointcut; Os pontos de junção são mais gerais e representam qualquer fluxo de controle onde 'podemos escolher' introduzir uma questão transversal, enquanto os pontos de junção identificam esses pontos de junção onde 'queremos' introduzir uma questão transversal.


1
Joinpoint - locais potenciais para aplicar / executar o código de conselho. Pointcut - pontos de junção reais escolhidos para executar o conselho.
user104309

24

Explicação leiga para alguém que é novo para os conceitos AOP. Isso não é exaustivo, mas deve ajudar na compreensão dos conceitos. Se você já está familiarizado com o jargão básico, pode parar de ler agora.

Suponha que você tenha uma classe normal Employee e deseja fazer algo sempre que esses métodos são chamados.

class Employee{
    public String getName(int id){....}
    private int getID(String name){...}
}

esses métodos são chamados de JoinPoints . Precisamos de uma maneira de identificar esses métodos para que o framework possa encontrar os métodos, entre todas as classes.métodos que carregou. Portanto, escreveremos uma expressão regular para corresponder à assinatura desses métodos. Embora haja mais do que isso, como você verá a seguir, mas vagamente, essa expressão regular é o que define o Pointcut . por exemplo

* * mypackage.Employee.get*(*)

O primeiro * é para o modificador público / privado / protegido / padrão. O segundo * é para o tipo de retorno do método.

Mas então você também precisa dizer mais duas coisas:

  1. Quando uma ação deve ser realizada - por exemplo, antes / depois da execução do método OU na exceção
  2. O que deveria fazer quando corresponder (talvez apenas imprimir uma mensagem)

A combinação dos dois é chamada de Conselho .

Como você pode imaginar, você teria que escrever uma função para poder fazer o # 2. Portanto, é assim que deve parecer para o básico.

Nota: Para maior clareza, use a palavra REGEX em vez de * * mypackage.Employee.get*(*). Na realidade, a expressão completa entra na definição.

@Before("execution(REGEX)")
public void doBeforeLogging() {....}   <-- executed before the matching-method is called

@After("execution(REGEX)")
public void doAfterLogging() {....}  <-- executed after the matching-method is called

Depois de começar a usá-los um pouco, você pode acabar especificando muitos avisos @ After / @ Before / @ Around. As expressões regulares repetidas acabarão tornando as coisas confusas e difíceis de manter. Portanto, o que fazemos é apenas dar um nome à expressão e usá-la em todos os outros lugares da classe Aspect.

@Pointcut("execution(REGEX)") <-- Note the introduction of Pointcut keyword
public void allGetterLogging(){} <-- This is usually empty

@Before("allGetterLogging")
public void doBeforeLogging() {....}

@After("allGetterLogging")
public void doAfterLogging() {....}

BTW, você também gostaria de envolver toda essa lógica em uma classe, que é chamada de Aspect, e escreveria uma classe:

@Aspect
public class MyAwesomeAspect{....}

Para fazer todas essas coisas funcionarem, você teria que dizer ao Spring para analisar as classes para ler, entender e agir nas palavras-chave @ AOP. Uma maneira de fazer isso é especificando o seguinte no arquivo xml de configuração do spring:

<aop:aspectj-autoproxy>


1
Eu sou novo no AOP e esta explicação me ajudou a entender a relação entre Advice / Pointcuts / JoinPoints de forma bastante clara.
Jatin Shashoo

11

Comparando uma linguagem AOP como AspectJ com uma linguagem de consulta de dados como SQL, você pode pensar em pontos de junção (ou seja, todos os lugares em seu código onde você pode tecer código de aspecto) como uma tabela de banco de dados com muitas linhas. Um pointcut é como um carimbo SELECT que pode escolher um subconjunto de linhas / pontos de junção definido pelo usuário. O código real que você entrelaça nesses locais selecionados é chamado de conselho.


9

Definições

Conforme a documentação:

Ponto de junção: um ponto durante a execução de um programa, como a execução de um método ou o tratamento de uma exceção.

Você pode considerar Joint Points como eventos na execução de um programa. Se você estiver usando Spring AOP, isso se limitará à invocação de métodos. AspectJ oferece mais flexibilidade.

Mas você nunca lida com todos os eventos, pois você não come toda a comida do menu quando vai a um restaurante (eu não te conheço, você pode! Mas, certamente não). Portanto, você faz uma seleção de eventos a serem tratados e o que fazer com eles. Aqui vai Pointcuts . De acordo com a documentação,

Pointcut : um predicado que corresponde aos pontos de junção .

Aí você associa o que fazer com o Pointcut , aí vai o Conselho . De acordo com a documentação,

O conselho está associado a uma expressão de corte de ponto e é executada em qualquer ponto de junção correspondido pelo corte de ponto.

Código

package com.amanu.example;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * @author Amanuel Nega on 10/25/16.
 */
class ExampleBussinessClass {

    public Object doYourBusiness() {
        return new Object();
    }

}

@Aspect
class SomeAspect {

    @Pointcut("execution(* com.amanu.example.ExampleBussinessClass.doYourBusiness())")
    public void somePointCut() {
    }//Empty body suffices

    @After("somePointCut()")
    public void afterSomePointCut() {
        //Do what you want to do after the joint point is executed
    }

    @Before("execution(* *(*))")
    public void beforeSomePointCut() {
        //Do what you want to do before the joint point is executed
    }

}

Explicação do Código

  • ExampleBusinessClass quando procurado, é o nosso alvo!
  • doYourBusiness()é um possível ponto de união
  • SomeAspect é o nosso aspecto que se cruza com várias preocupações, como bunda ExampleBusinessClass
  • somePointCut()é uma definição de um corte de ponto que corresponde ao nosso ponto de junção
  • afterSomePointCut()é um conselho que será executado após nosso somePointCut corte de ponto que corresponda ao doYourBusiness() ponto de junta
  • beforeSomePointCut()também é um conselho que corresponde a todas as publicexecuções de método. Ao contrário afterSomePointCut, este usa uma declaração de corte de ponto em linha

Você pode olhar a documentação se não acredita em mim. Eu espero que isso ajude


1
Explicação simples. Apenas três textos citados são suficientes para entender. Obrigado.
TRiNE

6

Ambos pertencem ao "onde" da programação orientada a aspectos.

Um ponto de junção é um local individual onde você pode executar código com AOP. Por exemplo, "quando um método lança uma exceção".

Um pointcut é uma coleção de pontos de junção. Por exemplo, "quando um método da classe Foo lança uma exceção".


4

JoinPoint : Joinpoint são pontos na execução do seu programa onde o fluxo de execução foi alterado como captura de exceção, chamada de outro método.

PointCut : PointCut são basicamente aqueles pontos de junção onde você pode colocar seu conselho (ou aspecto de chamada).

Basicamente, os PointCuts são o subconjunto dos JoinPoints .


3

AOP na primavera tem {Advisor, Advice, Pointcut, Joinpoint}

Como você sabe, o objetivo principal do aop é separar a lógica de preocupação transversal (Aspecto) do código do aplicativo, para implementar isso no Spring que usamos (Conselho / Consultor)

Pointcut é usado para filtrar onde queremos aplicar este conselho exatamente, como "todos os métodos começam com insert", então outros métodos serão excluídos, por isso temos na interface Pointcut {ClassFilter e MethodMatcher}

Portanto, o Conselho é a implementação da lógica transversal e o Advisor é o conselho mais o PointCut, se você usar apenas o conselho, o Spring irá mapeá-lo para o conselheiro e tornar o pointcut TRUE, o que significa não bloquear nada. É por isso que, quando você usa apenas conselhos, ele é aplicado a todos os métodos da classe de destino, porque você não os filtrou.

Mas Joinpoint é um local no programa, você pode pensar nisso como uma reflexão quando você acessa o objeto Class e então você pode obter o objeto Method, então você pode invocar qualquer método nesta classe, e é assim que o compilador funciona, se você pensar como isso você pode imaginar o Joinpoint.

O Joinpoint pode ser com campo, construtor ou método, mas no Spring temos joinpoint apenas com métodos, é por isso que no Spring temos tipos de Joinpoint (Antes, Depois, Throws, Around), todos eles se referem a locais na classe.

Como mencionei, você pode ter conselhos sem corte de pontos (sem filtro), então eles serão aplicados a todos os métodos ou você pode ter um conselheiro que é [conselho + corte de pontos] que será aplicado a métodos específicos, mas você não pode ter conselhos sem joinpoint como pointcut, você tem que especificá-lo, e é por isso que os tipos de conselhos na primavera são exatamente os mesmos tipos do ponto de junção, então quando você escolhe um conselho você escolhe implicitamente qual ponto de junção.

Para finalizar, o conselho é a lógica de implementação para o seu aspecto para a classe de destino, este conselho deve ter um ponto de junção como antes da invocação, após a invocação, depois de lançar ou em torno da invocação, então você pode filtrar onde exatamente deseja aplicá-lo usando pointcut para filtrar os métodos ou sem pointcut (sem filtro) para que seja aplicado a todos os métodos da classe.


3

Um pointcut é definido na implementação da classe Aspect. O corte de ponto basicamente se refere à expressão de corte de ponto dentro do conselho.

Por exemplo,

@Before("execution(* app.purchase2.service.impl.*(..))")
public void includeAddOns(RolesAllowed roles) {
..
}

O acima significa, o método "includeAddOns" é chamado antes de invocar (devido ao conselho @Before) qualquer método (nas classes dentro do pacote "app.purchase2.service.impl")

Toda a anotação é chamada de ponto de corte @Before("execution(* app.purchase2.service.impl.*(..))")

O ponto comum é a chamada do método real, que uniu o método no pacote "app.purchase2.service.impl" ao método na classe de aspecto "includeAddOns ()".

Você pode acessar as propriedades do ponto de junção com a org.aspectj.lang.JoinPointclasse.


Boa resposta! Finalmente entendi a diferença!
Dante,

2

Eu concordo com mgroves .. Um corte de ponto pode ser considerado como uma coleção de pontos de articulação múltiplos. Ponto de junção especifica o local particular onde o conselho pode ser implementado, onde um ponto de corte reflete a lista de todos os pontos de junção.


0

JoinPoint: especifica um ponto (método) na aplicação onde o Advice será executado.

Pointcut: É uma combinação de JoinPoints e especifica onde o Conselho de JoinPoint será executado.


-5

ponto de junção é um lugar onde colocamos os conselhos

mas o corte de ponto é a coleção de pontos de junção. isso significa de quantas maneiras nós configuramos a lógica de corte transversal é chamado de corte de ponto

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.