Se eu tiver uma anotação @Transactional em um método privado em um bean Spring, a anotação terá algum efeito?
Se a anotação @Transactional estiver em um método público, ela funcionará e abrirá uma transação.
public class Bean { public void doStuff() { doPrivateStuff(); } @Transactional private void doPrivateStuff() { } } ... Bean bean = (Bean)appContext.getBean("bean"); bean.doStuff();
A resposta é a sua pergunta – a @Transactional não terá efeito se usada para anotar methods privados. O gerador de proxy irá ignorá-los.
Isto está documentado no capítulo 10.5.6 do Manual da spring :
Visibilidade do método e @Transactional
Ao usar proxies, você deve aplicar a anotação @Transactional somente a methods com visibilidade pública. Se você anotar methods protegidos, privados ou visíveis a pacotes com a anotação @Transactional , nenhum erro será gerado, mas o método anotado não exibirá as configurações transacionais configuradas. Considere o uso de AspectJ (veja abaixo) se você precisar anotar methods não públicos.
A pergunta não é privada ou pública, a pergunta é: como ela é invocada e qual implementação AOP você usa!
Se você usar (padrão) Spring Proxy AOP, então todas as funcionalidades AOP fornecidas pelo Spring (como @Transational ) serão consideradas somente se a chamada passar pelo proxy. – Este é normalmente o caso se o método anotado for chamado a partir de outro bean.
Isso tem duas implicações:
Como os methods privados não devem ser chamados de outro bean (a exceção é reflexo), sua Anotação @Transactional não é levada em conta.
Se o método for público, mas for invocado a partir do mesmo bean, ele não será levado em consideração (esta instrução é correta apenas se (padrão) for utilizado o Spring Proxy AOP).
@ See Spring Reference: Chapter 9.6 9.6 Mecanismos de proxies
IMHO você deve usar o modo aspectJ, em vez dos Spring Proxies, que irão superar o problema. E os Aspectos Transacionais AspectJ são tecidos até mesmo em methods privados (verificados no Spring 3.0).
Por padrão, o atributo @Transactional funciona somente ao chamar um método anotado em uma referência obtida de applicationContext.
public class Bean { public void doStuff() { doTransactionStuff(); } @Transactional public void doTransactionStuff() { } }
Nota: No modo de proxy (que é o padrão), somente chamadas de método ‘externas’ que entram através do proxy serão interceptadas. Isso significa que ‘auto-invocação’, ou seja, um método dentro do object de destino que chama algum outro método do object de destino, não levará a uma transação real em tempo de execução, mesmo se o método invocado estiver marcado com @Transactional !
Considere o uso do modo AspectJ (veja abaixo) se você espera que as auto-invocações sejam envolvidas com transactions também. Neste caso, não haverá um proxy em primeiro lugar; em vez disso, a class de destino será ‘tecida’ (ou seja, seu código de byte será modificado) para transformar @Transactional em comportamento de tempo de execução em qualquer tipo de método.
Sim, é possível usar @Transactional em methods privados, mas, como outros já mencionaram, isso não funcionará imediatamente. Você precisa usar AspectJ. Demorei algum tempo para descobrir como fazê-lo funcionar. Eu vou compartilhar meus resultados.
Eu escolhi usar tecelagem em tempo de compilation em vez de tecelagem em tempo de carregamento porque acho que é uma opção melhor em geral. Além disso, estou usando o Java 8, portanto, talvez seja necessário ajustar alguns parâmetros.
Primeiro, adicione a dependência para aspectjrt.
org.aspectjaspectjrt1.8.8
Em seguida, adicione o plugin AspectJ para fazer o tecimento de bytecode real no Maven (isso pode não ser um exemplo mínimo).
Agora você deve poder usar @Transactional em methods privados.
Uma ressalva para esta abordagem: Você precisará configurar o seu IDE para estar ciente de AspectJ caso contrário, se você executar o aplicativo via Eclipse, por exemplo, pode não funcionar. Certifique-se de testar contra uma configuração direta do Maven como uma verificação de integridade.
Por favor veja este documento:
No modo proxy (que é o padrão), somente as chamadas de método externo que chegam pelo proxy são interceptadas. Isso significa que a auto-chamada, na verdade, um método dentro do object de destino que chama outro método do object de destino, não levará a uma transação real em tempo de execução, mesmo se o método chamado estiver marcado com @Transactional.
Considere o uso do modo AspectJ (consulte o atributo mode na tabela abaixo) se você espera que as auto-chamadas também sejam agrupadas com transactions. Neste caso, não haverá um proxy em primeiro lugar; em vez disso, a class de destino será modificada (isto é, seu código de byte será modificado) para transformar @Transactional em comportamento de tempo de execução em qualquer tipo de método.
—————————-sobre
então, anher maneira é usuário BeanSelfAware
A resposta é não. Por favor, veja Spring Reference: Usando @Transactional :
A anotação @Transactional pode ser colocada antes de uma definição de interface, um método em uma interface, uma definição de class ou um método público em uma class