@Transaction @async e outras anotações não funcionam
Antes, muitas pessoas encontraram algumas situações em que a anotação não funciona ao usar @Transaction, @async e outras anotações na primavera.
Por que essas situações ocorrem? Como as funções dessas anotações são realmente implementadas pela Spring AOP e seus princípios de implementação são implementados por meio de proxy.
JDK Proxy dinâmico
Vamos entender os princípios básicos da proxy dinâmica do JDK com um exemplo simples:
// Classe de destino Interface Interface pública jdkProxytestService {void run ();} // class classe pública JDKProxyTestServiceImpl implementa jdkproxytestService {public void run () {System.out.println ("faça algo ..."); }} // classe de proxy classe public TestJDKProxy implementa InvocationHandler {Private Object TargetObject; // Objeto de destino do proxy // Construa o objeto proxy Public Object NewProxy (Object TargetObject) {this.TargeGetObject = TargetObject; return proxy.newproxyInstance (TargetObject.getClass (). getClassLoader (), TargetObject.getClass (). getInterfaces (), este); } // Use a reflexão para executar o aprimoramento lógico no objeto público lógico original Invoke (proxy do objeto, método do método, objeto [] args) lança lançável {// simular a transação iniciar assumebegintransaction (); // Objeto de lógica de execução original ret = Method.inVoke (TargetObject, args); // Mock Transaction Submission assumecommittransaction (); retornar retorno; } private void assumeBegIntransaction () {System.out.println ("Mock Transaction Start ..."); } private void assumeCommittransaction () {System.out.println ("Mock Transaction Submission ..."); }} // teste public class Test {public static void main (string [] args) {testJdkProxy jdkProxy = new testJdkProxy (); JDKProxyTestService Proxy = (JDKProxyTestService) JDKProxy.NewProxy (novo JDKProxyTestServiceImpl ()); proxy.run (); }}O exemplo acima deve ser capaz de explicar claramente o princípio do proxy dinâmico do JDK. Ele usa o mecanismo de reflexão para gerar uma classe anônima que implementa a interface proxy e chamadas InvokeHandler para lidar com isso antes de chamar o método específico. Quando chamamos um método por meio de um objeto de classe proxy, chamaremos seu método Invoke primeiro e depois chamaremos o método original. Dessa forma, podemos adicionar a lógica de processamento uniformemente antes e depois da lógica do método original.
A primavera também possui um método dinâmico de proxy que é o proxy dinâmico do CGLIB. Ele carrega o arquivo de classe da classe de objeto proxy e o processa modificando seu bytecode para gerar subclasses. Embora os métodos de manuseio sejam diferentes, as idéias da agência são consistentes.
Se o objeto de destino for proxyed implementar uma interface, o Spring usará o proxy dinâmico do JDK por padrão. Todas as interfaces implementadas por esse tipo de destino serão proxyed. Se o objeto de destino não implementar nenhuma interface, um proxy do CGLIB será criado.
Falha e resolução da anotação da Spring AOP
Com base na análise acima do princípio dinâmico de proxy, vejamos os dois problemas comuns a seguir:
Na mesma classe, o método A chama o método b (anotado no método b) e a anotação é inválida.
Para todas as anotações da Spring AOP, se a primavera encontrar essas anotações ao digitalizar feijões, ela construirá dinamicamente um objeto de proxy.
Esta anotação é válida se você deseja chamar diretamente o método A com anotação através de um objeto da classe X. Porque neste momento, a primavera determinará que existe uma anotação AOP no método que você está prestes a ligar e, em seguida, usará o objeto proxy da classe X para chamar o método A.
Mas suponha que o método A na classe X chamará o método B com anotação e você ainda deseja chamar o método A através do objeto da classe X, a anotação no método B é inválida. Como a primavera determina que o A que você chama não possui anotação, o objeto original ainda é usado em vez do objeto proxy. Quando A chama B a seguir, a anotação do método B no objeto original é obviamente inválida.
Solução:
É claro que a maneira mais fácil é fazer com que os métodos A e B não têm dependências e podem chamar diretamente o método B através do objeto da classe X.
Mas muitas vezes, nossa lógica pode não estar bem escrita dessa maneira, então há outro método: encontre uma maneira de obter manualmente o objeto proxy.
A classe AOPContext possui um método CurrentProxy () que pode obter diretamente o objeto proxy da classe atual. Então o exemplo acima pode ser resolvido assim:
// Método de chamada B Inside Método A // 1. Ligue diretamente B, a anotação é inválida. B () // 2. Obtenha o objeto de classe proxy e ligue para B. ((x) aopContext.CurrentProxy ()). B ()
O objeto @Autowired é nulo no método de anotação AOP
Em uso anterior, no método de anotação, ao usar outros objetos injetados, verificou -se que o objeto não foi injetado e era nulo.
Finalmente, verificou -se que o motivo disso foi porque o método era privado. Como a Spring usa o proxy dinâmico do JDK ou o proxy dinâmico do CGLIB, um é uma classe que implementa a interface e o outro é implementado por meio de subclasses. Nem a interface nem a classe pai, o método privado poderá estar presente, caso contrário, nem a subclasse nem a classe de implementação podem ser substituídas.
Se o método for privado, esse método não poderá ser encontrado no processo de proxy, causando problemas na criação de objetos de proxy e fazendo com que alguns objetos não sejam injetados.
Portanto, se o método precisar usar as anotações da AOP, defina-o como um método não privado.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.