The implementation principle of interceptors is very simple, that is, dynamic agent, implement AOP mechanism. When an external call to intercept the bean interception method, you can choose to intercept before or after the interception method to execute the logic, such as special permission validation, parameter correction and other operations.
But recently, in a project, you want to work across data sources in a single transaction. Database cross-source is not here to say, you can own Baidu.
The problem here is that if we are going to intercept multiple methods of a class and use this in a method of that class to invoke the method to intercept, it will cause the interception to fail.
This is a bit abstract, look at a code:
PackageCom.intsmaze.before; Public classAopdemo {/*** The logical service method called by the controller layer, which internally invokes the service method that accesses different databases separately*/ Public voidFindinforall () { This. Finddatabasea (); This. FINDDATABASEB (); } /*** Here we'll check a table for a database .*/ Public voidFinddatabasea () {}/*** Here we're going to query a table for B database .*/ Public voidFinddatabaseb () {}}
We then use spring's AOP to write a class for cut-in, which is basically executing some code before executing Finddatabasea and FINDDATABASEB to tell the address of the query database of the subsequent query operation.
@Aspect Public class authaspect{ // match the execution of the Aopdemo class / /All methods under the Com.intsmaze.before package as a pointcut @Before ("Execution (* com.intsmaze.before.AopDemo. * (..))" ) publicvoid Authority () { System.out.println (" Impersonation execution Permission Check ");} }
Then I'll explain it in parables, understand the premise of my metaphor you need to know what the dynamic agent is, and make an inappropriate analogy, is to dynamically generate a new * * Class (note not the object).
We can see this here. When executing findinforall, AOP monitors this method to be intercepted and generates a proxy class, which is a new class.
Public classaopdemo+Other Name {/*** The logical service method called by the controller layer, which internally invokes the service method that accesses different databases separately*/ Public voidFindinforall () {//---------------------------------------------------System.out.println ("Impersonation Execution Permission Check"); //--------------------------------------------------- This. Finddatabasea (); This. FINDDATABASEB (); } /*** Here we'll check a table for a database .*/ Public voidFinddatabasea () {}/*** Here we're going to query a table for B database .*/ Public voidFinddatabaseb () {}}
As we can see here, we actually generate a new class, which in the first line of the Findinforall method adds the method that AOP specifies to execute. What we call in our system is the Findinforall method of this proxy class , and the This.finddatabasea () in this method, This.finddatabaseb (), is not to be intercepted by AOP, Because the package name and class name of the AOP interception are obviously different from the proxy class, this is why the internally invoked method cannot be intercepted. I do not know that, we understand it. on how to write dynamic Agent with JDK, I will review the previous notes during the holiday and write them out.
How to solve it? We started thinking about the use of this internal call when avoiding AOP cut-in classes, but found that this increased the complexity of the code structure, which would have required only one class and finally managed with two classes. Too troublesome.
Then consider the progress of the project, using the logic code encapsulated as a tool method for invocation.
On-line search data have the method can solve, no test.
HTTP://BLOG.CSDN.NET/QUZISHEN/ARTICLE/DETAILS/5803721 Below is the main idea.
In spring's source code, it is frustrating to see whether the current internal call is executed using a proxy through an enhanced object check. The authors of spring are very vague about ways to avoid internal calls.
We might want to call two times outside the Beana, call method1 for the first time, call METHOD2 for the second time, this will solve the problem, but the direct result is that our logic code will become disorganized, not all scenarios can be done by such a design. Although this is the idea that spring officially recommends to avoid internal calls.
Looking at the relevant data, we get a method, that is, in the internal method1, through the direct acquisition of the current proxy object and then through the proxy object call METHOD2, so trigger interception.
Look at the code:
public void Method1 () {Logger.error ( "1" // If the internal method that you want to invoke is also intercepted, you must use the context to get the proxy object to execute the call. You cannot intercept the if (null != Aopcontext.currentproxy ()) {((Norquicknewsdao) Aopcontext.currentproxy ()). METHOD2 (); else {method2 (); }} public void Method2 () {Logger.error ( "2"
We show a call to Aopcontext to get the current proxy object and then call its method, and one of the steps required is to expose the current proxy to the thread, and configure a parameter in the configuration file:
<name= "Exposeproxy"> <value> true</value> </Property>
It is a parameter of Proxyconfig, the default is False, if this parameter is not set, then the above Java code will not be able to get the proxy object in the current thread.
This method can trigger interception successfully, but also brings other problems, such as code weaving, our code will become complex and obscure, and strict requirements of the system for the current bean must configure the interceptor, otherwise it will not find the interceptor and throw an exception.
What is the negative impact of this? The impact on the business, the impact on security, is now unknown and needs to be tested to try.
Spring AOP does not intercept methods that are called from within an object