Pergunta

Eu quero saber o que realmente acontece quando você anota um método com @Transactional? Obviamente, eu sei que a primavera envolverá esse método em uma transação.

Mas, eu tenho as seguintes dúvidas:

  1. Ouvi dizer que a primavera cria um Classe de proxy? Alguém pode explicar isso em mais profundidade. O que realmente reside nessa aula de proxy? O que acontece com a classe real? E como posso ver a classe proxiada criada pela Spring
  2. Eu também li nos documentos da primavera que:

Nota: Como este mecanismo é baseado em proxies, Somente o método 'externo' chamadas de proxy serão interceptadas. Isso significa que 'auto-investigação', ou seja, um método dentro do objeto de destino que chama algum outro método do objeto de destino, não levará a uma transação real em tempo de execução, mesmo que o método invocado seja marcado com @Transactional!

Fonte: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

Por que apenas as chamadas de método externas estarão sob transação e não os métodos de auto-divisão?

Foi útil?

Solução

Este é um grande tópico. O documento de referência da primavera dedica vários capítulos a ele. Eu recomendo ler aqueles Programação Orientada a Aspectos e Transações, como o suporte declarativo da transação da primavera usa a AOP em sua fundação.

Mas em um nível muito alto, a primavera cria proxies para aulas que declaram @Transaction na própria classe ou nos membros. O proxy é principalmente invisível em tempo de execução. Ele fornece uma maneira de a primavera injetar comportamentos antes, depois ou ao redor do método chama para o objeto que está sendo proxado. O gerenciamento de transações é apenas um exemplo dos comportamentos que podem ser ligados. As verificações de segurança são outra. E você também pode fornecer o seu próprio para coisas como log. Então, quando você anota um método com @Transaction, Spring cria dinamicamente um proxy que implementa a mesma interface da classe que você está anotando. E quando os clientes fazem chamadas em seu objeto, as chamadas são interceptadas e os comportamentos injetados através do mecanismo de proxy.

As transações no EJB funcionam da mesma forma, a propósito.

Como você observou, através, o mecanismo de proxy só funciona quando as chamadas vêm de algum objeto externo. Quando você faz uma chamada interna dentro do objeto, você está realmente fazendo uma ligação através do "isto"Referência, que ignora o proxy. Existem maneiras de contornar esse problema, no entanto. Eu explico uma abordagem em Este post do fórum em que eu uso um BeanFactoryPostProcessor Injetar uma instância do proxy nas classes de "auto-referência" em tempo de execução. Eu salvo essa referência a uma variável de membro chamada "Eu". Então, se eu precisar fazer chamadas internas que exijam uma alteração no status da transação do fio, dirijo a chamada através do proxy (por exemplo"me.somemethod ()".) O post do fórum explica com mais detalhes. Observe que o BeanFactoryPostProcessor O código seria um pouco diferente agora, pois foi escrito no período da primavera 1.x. Mas espero que isso lhe dê uma ideia. Eu tenho uma versão atualizada que provavelmente poderia disponibilizar.

Outras dicas

Quando a mola carrega suas definições de feijão e foi configurada para procurar anotações @Transaction, ele criará esses objetos proxy em torno do seu feijão real. Esses objetos de proxy são instâncias de classes geradas automaticamente em tempo de execução. O comportamento padrão desses objetos de proxy quando um método é chamado é apenas para invocar o mesmo método no feijão "Target" (ou seja, seu feijão).

No entanto, os proxies também podem ser fornecidos com interceptores e, quando presentes, esses interceptores serão invocados pelo proxy antes de invocar o método do seu alvo. Para os feijões -alvo anotados com @Transaction, a primavera criará um transactionInterceptor e o passará para o objeto Proxy gerado. Portanto, quando você chama o método do código do cliente, está chamando o método no objeto Proxy, que primeiro chama o transactionInterceptor (que inicia uma transação), que por sua vez chama o método no seu feijão de destino. Quando a invocação termina, o TransactionInterceptor comete/rola a transação. É transparente para o código do cliente.

Quanto à coisa do "método externo", se o seu feijão invocar um de seus próprios métodos, não o fará através do proxy. Lembre -se, a primavera envolve seu feijão no proxy, seu feijão não tem conhecimento disso. Somente chamadas de "fora" do seu feijão passam pelo proxy.

Isso ajuda?

Como pessoa visual, gosto de pesar com um diagrama de sequência do padrão de proxy. Se você não sabe como ler as flechas, li o primeiro assim: Client executa Proxy.method().

  1. O cliente chama um método no alvo de sua perspectiva e é silenciosamente interceptado pelo proxy
  2. Se um aspecto antes for definido, o proxy o executará
  3. Então, o método real (destino) é executado
  4. Pós-retorno e pós-arremesso são aspectos opcionais que são executados após o retorno do método e/ou se o método lançar uma exceção
  5. Depois disso, o proxy executa o aspecto posterior (se definido)
  6. Finalmente, o proxy retorna ao cliente de chamada

Proxy Pattern Sequence Diagram(Fui autorizado a postar a foto em condição que mencionei suas origens. Autor: Noel Vaes, site: www.noelvaes.eu)

A resposta mais simples é, Em qualquer método que você declare @Transaction, o limite da transação é iniciado e o limite termina quando o método é concluído.

Se você estiver usando a chamada JPA, todas as confirmações estão nesse limite de transação. Digamos que você esteja salvando entidade1, entidade2 e entidade3. Agora, enquanto Saving Entity3 ocorre, ocorre uma exceção, pois o Enitiy1 e o Entity2 vem na mesma transação, para que a entidade1 e a entidade2 sejam revertidos com entidade3.

Transação: (Entity1.Save, Entity2.Save, Entity3.Save). Qualquer exceção resultará em reversão de todas as transações JPA com DB. A transação JPA internamente é usada pela primavera.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top