The core concepts of AOP
Fully understanding Spring AOP begins with understanding AOP’s core concepts and terminology, which is not specified by Spring and, unfortunately, is not intuitive, but it can be even more confusing if Spring uses its own terminology.
- Aspect: An Aspect, a modular object consisting of a series of pointcuts, enhancements, and imports that defines priorities and thus influences the order in which enhancements and imports are performed. Transaction Management is a good example of this aspect in Java enterprise applications.
- Join point: an access point at which a program is executed, such as method execution, class initialization, exception handling. In Spring AOP, access points always represent method execution.
- Advice: Enhanced, section actions performed at a specific access point, including various types such as “around,” “before” and “after”. Many AOP frameworks, including Spring, typically implement enhancements using interceptors, maintaining a chain of interceptors around access points.
- Pointcut: Pointcut, a predicate (expression) used to match a particular access point. Enhancements will be associated with Pointcut expressions and run on any access point that pointcuts match. Matching access points through pointcut expressions is at the heart of AOP, and Spring uses AspectJ’s pointcut expressions by default.
- Introduction: To declare additional methods and fields for a type. Spring AOP allows you to introduce any interface and its default implementation into an enhanced object.
- Target object: A Target object that is enhanced by one or more facets. Also called enhanced objects. Since Spring AOP has used runtime proxies, the target object will always be a proxy object.
- AOP Proxy: AN AOP proxyTo implement the aspect function, an object is created by the AOP framework. The default approach to AOP proxies in the Spring framework is to use the interface-based JDK dynamic proxy if you have an interface, or the class-based CGLIB dynamic proxy if you don’t. But we can set it up
proxy-target-class="true"
, fully using CGLIB dynamic proxy. - Has: weaveLink one or more facets with a class or object to create an enhanced object. Weaving can occur at compile time (using the AspectJ compiler), load time, or runtime. Spring AOP is run time weaving by default and can be passed
Enumeration AdviceMode
To set up.
Simulate the execution of aspect advice
Instead of showing the test code, we simulate the execution of aspect advice with simple code.
Although Spring AOP is implemented through dynamic proxies, we can bypass proxies and directly simulate its execution, with example code:
package doubt;
public class AspectAdviceInvokeProcess {
public static void main(String[] args){
try {
// Normal execution
AspectInvokeProcess(false);
System.out.println("===== splitter =====");
// Exception execution
AspectInvokeProcess(true);
} catch (Exception e) {
// TODO Auto-generated catch blocke.printStackTrace(); }}/** * Section execution process *@param isException
* @throws Exception
*/
public static void AspectInvokeProcess(boolean isException) throws Exception{
try {
try {
aroundAdvice(isException);
} finally {
afterAdvice();
}
afterReturningAdvice();
return;
} catch (Exception e) {
afterThrowingAdvice(e);
throw e;
return; }}/** * Surround enhancement *@param isException
* @throws Exception
*/
private static void aroundAdvice(boolean isException) throws Exception {
System.out.println("around before advice");
try {
JoinPoint_Proceed(isException);
} finally {
System.out.println("around after advice"); }}/** * Braided access point execution process *@param isException
*/
public static void JoinPoint_Proceed(boolean isException){
beforeAdvice();
targetMethod(isException);
}
/** ** ** */
private static void beforeAdvice(a) {
System.out.println("before advice");
}
/** * target method *@param isException
*/
private static void targetMethod(boolean isException) {
System.out.println("Target method execution");
if(isException)
throw new RuntimeException("Abnormal occurrence");
}
/** * post-enhanced */
private static void afterAdvice(a) {
System.out.println("after advice");
}
/** * Returns normal enhancement */
private static void afterReturningAdvice(a) {
System.out.println("afterReturning");
}
/** * Exception return enhancement *@param e
* @throws Exception
*/
private static void afterThrowingAdvice(Exception e) throws Exception {
System.out.println("afterThrowing:"+e.getMessage()); }}Copy the code
Same aspect, different order of advice
The execution result of the above code directly reflects the execution order of different advice in the same APsect. The result is as follows:
Around before advice before advice target method Executes around after advice after advice afterReturning ===============分 线============== around before advice before advice Target method Executes around after advice after advice AfterThrowing: exception is Java. Lang. RuntimeException: exception occursCopy the code
Conclusion:
Different aspects, order of execution of advice
Details can be seen, “Spring the official document” docs. Spring. IO/Spring/docs…
Spring AOP controls the order in which different aspects and advice are executed by specifying the aspect priority in two ways:
-
Aspect class to add comments: org. Springframework. Core. The annotation. Order, using annotations the value attribute specified priority.
-
Aspect class implementing an interface: org. Springframework. Core. Ordered, realize Ordered interface getOrder () method.
Where, the lower the value is, the higher the priority is. @Order defaults to the lowest priority, that is, the maximum value:
/**
* Useful constant for the lowest precedence value.
* @see java.lang.Integer#MAX_VALUE
*/
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
Copy the code
Finally, different aspects, the order of advice execution:
- Entry operations (Around (Before execution) and Before), the higher the priority, the earlier the execution;
- The access point is not executed until the entry operation of one section is completed and all the next sections are completed.
- Outgoing operations (Around (After ap execution), After, AfterReturning, AfterThrowing), the lower the priority, the earlier the execution.
- The output operation of one slice is completed, and all the next faces are not turned until the call point is returned.
As shown below:
First in, last out, last in, first out
Same aspect, same order of advice
The execution Order of the same advice in the same aspect cannot be directly determined, and @order is also invalid in the advice method, but there are two workarounds:
- Combine the two advice into one advice, and the order of execution can be controlled by the code
- Separate the two advice into their respective aspects, and then specify the order of execution for the aspect
The Transactional Aspect priority
Spring Transaction Management is also based on Spring AOP.
In the use of Spring AOP, it is sometimes necessary to specify that a custom aspect has a lower or higher priority than a Transaction aspect, so we need to know:
- Transaction aspect Priority: Defaults to the lowest priority
LOWEST_PRECEDENCE = Integer.MAX_VALUE
Copy the code
- The type of enhancement for a transaction: Around advice. It is not hard to understand that an entry method opens a transaction and an exit method commits or rolls back, so you need to surround the enhancement.
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport implements DisposableBean {
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
setTransactionAttributeSource(tas);
}
@SuppressAjWarnings("adviceDidNotMatch")
Object around(final Object txObject): transactionalMethodExecution(txObject) {
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
try {
return invokeWithinTransaction(methodSignature.getMethod(), txObject.getClass(), new InvocationCallback() {
public Object proceedWithInvocation(a) throws Throwable {
returnproceed(txObject); }}); }catch (RuntimeException ex) {
throw ex;
}
catch (Error err) {
throw err;
}
catch (Throwable thr) {
Rethrower.rethrow(thr);
throw new IllegalStateException("Should never get here", thr); }}}Copy the code
- How to modify the transaction priority areas of: in open transaction, by setting the @ EnableTransactionManagement and – driven / > < tx: an annotation, in the order attribute to modify the transaction section of priority. Details can be seen, “Spring the official document” docs. Spring. IO/Spring/docs…