This is the 21st day of my participation in the August Text Challenge.More challenges in August

Goal:

1. What is AOP and AspectJ?

  1. What is Spring AOP

  2. Spring AOP Annotation edition implementation principles

  3. Spring AOP aspect principle analysis


First, understand AOP

1.1 What is AOP

Aop is oriented to section programming, compared with traditional OOP, AOP can be in the method of the front, middle, after the insertion of logic code, for a large number of logic repeat code in the project, the use of AOP can be very good closure logic, logic independent from business code, one writing, multiple use.

AOP is a complement to Object Oriented Programming (OOP).

OOP can solve the problem of object data and encapsulation, but not the problem of Aspect (” Aspect “) separation. Here are some examples to illustrate.

For example, we have a Bank class. Bank has two methods, save and withdraw.

Classes and methods are defined as follows:

package com.lxl.www.aop; Public class Bank {/** * public Float save(Account Account, Float money) { Return null; } return Float withdraw(Float money, Float money) {return Float withdraw(Float money, Float money); }};Copy the code

These two methods involved important information such as the user’s account funds and had to be very careful, so after writing the above business logic, the project leader proposed a new requirement — to add security authentication features to every important method of the Bank class.

So, we add security code to the two methods

The modified classes and methods are as follows:

Public class Bank {public Float save(Float money, Float money) {public Float save(Float money, Float money) { Return null; } public Float withdraw(Float money) {Float withdraw(Float money) { Return null; }};Copy the code

Both methods needed to operate on the database, and to maintain data integrity, the project leader added transaction control to each method of the Bank class that operated on the database.

Therefore, we had to add security authentication code to each of the above methods.

Classes and methods are defined as follows:

package com.lxl.www.aop; Public class Bank {/** * save money */ public Float save(Account Account, Float money) {// Verify that the account is valid // begin Transaction // Increase the amount of money in the account, return the current amount of money in the account // end Transaction Return null; } /** * take money */ public Float withdraw(Account, Float money) {// Verify that the account is a valid user // begin Transaction // Reduce the amount of money in the account, return the amount of money removed // end Transaction return null; }};Copy the code

 

We see this kind of repetitive code all over the program that has nothing to do with business logic. There are far more than two classes and functions involved in real engineering projects. How to solve this problem?

AOP was invented to solve this problem. Enhancements can be achieved without modifying the code

1.2 Related concepts of AOP

  • Aspect: The component that encapsulates common business logic, the code content we want to insert. In Spring AOP, aspects can be implemented using a generic class-based pattern, or with the @aspect annotation in a generic class

  • Join points: Join points are points at which facets can be inserted during application execution. Simple to understand, can be understood as the need to enhance the method.

  • Advice: Used to specify where the action is, before or after the method, and so on

    • Before notification – Call notification before the target method is called
    • After Notification – The notification is called after the target method completes (regardless of whether the program has an exception), without caring what the output of the method is
    • Return notification – Notification is called after successful execution of the target method
    • Exception Notification (after-Throwing) – Calls the notification after the target method throws an exception
    • Around advice (around) – Advice wraps around the notified method, performing custom behavior before and after the notified method invocation
  • Target: The target object is the object to be enhanced, that is, the class object containing the main business logic

  • PointCut: Specifies which Bean components and which methods use aspect components. Example: when executing a method with a particular name. We define a pointcut (execution com.lxl.www.aop.. (..) How pointcut expressions match join points is at the heart of AOP. Spring uses AspectJ pointcut semantics by default.

  • Weaving: The process of cutting notifications into joints is called Weaving

  • Introductions: You can introduce other interfaces or implementations dynamically into targetClass

Look at the picture above to see what each region means

  

So what does using AOP in Spring mean that you need? Let’s take an example that implements the above bank example.

  • First we have a bank class

    package com.lxl.www.aop.bank; Public interface Bank {/** * save money */ Float save(Account Account, Float money); Float withdraw(Float withdraw, Float money); };Copy the code
  • There is an implementation method for the bank class. Here, save and withdraw are the connection points. Eventually, various notifications are inserted into the join point

    package com.lxl.www.aop.bank; import org.springframework.stereotype.Service; /** ** DATE 2020/12/6. ** @author LXL. */ @service public implements Bank{@override public Float save(Account Account, Float money) { System.out.println(account.getName() + "account.getName" + money); return null; } @override public Float withdraw(Account Account, Float money) { System.out.println(account.getName() + "account.getName" + money); return null; }}Copy the code
    • Next, we have a section, and the section is a class. The section class defines pointcuts, notifications, and references
    package com.lxl.www.aop.bank; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.DeclareParents; import org.aspectj.lang.annotation.Pointcut; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; Public class BankLogAspect () {/** * BankLogAspect () {/** * BankLogAspect (); For the com. LXL. www.aop.bank.IcbcBank introduced an interface EnhanceFunctionOfBank, * at the same time, The introduction of the default implementation class IcbcEnhanceFunctionOfBank * / @ DeclareParents (value = "com. LXL. www.aop.bank.IcbcBank," / / introduction of the target class. Is the need to introduce the realization of dynamic class defaultImpl = IcbcEnhanceFunctionOfBank. / / introduction of the default implementation of the interface class) public static EnhanceFunctionOfBank enhanceFunctionOfBank; / / introduction of the interface/define a tangent point * * * * / the @pointcut (" execution (* * com. LXL. www.aop.bank.IcbcBank. (..) ") public void pointCut() {} @param joinPoint */ @before (value = "pointCut()") public void beforeAdvice(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println(" Execute target method "+ pre-notification for methodName+"); } @afteradvice (value = "pointCut()") public void afterAdvice(JoinPoint JoinPoint) {String methodName = joinPoint.getSignature().getName(); System.out.println(" Execute target method "+ postnotification for methodName+"); } @afterreturning (value = "pointCut()", returning = "result") public void returningAdvice(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); System.out.println(" execute target method "+ return notification for methodName+"); } /** * defines an exception */ @afterthrowing (value = "pointCut()") public void throwingAdvice(JoinPoint JoinPoint) {String methodName = joinPoint.getSignature().getName(); System.out.println(" Execute target method "+methodName+" exception notification "); }}Copy the code

    So who is the target here? That’s our IcbcBank class. The important thing to note here is import: import is the concept of an interface being dynamically implemented by another class. In this way, the class that implements the interface can dynamically own the functionality of the interface implementation class.

  • Additional functions of banks. In other words, banks can deposit money and withdraw money. There is an additional feature. For example, not every bank has financial management.

    package com.lxl.www.aop.bank; /** * enhanced functionality */ public interface EnhanceFunctionOfBank {void management (Account Account); }Copy the code
  • An implementation class for the additional functionality of a concrete bank

    package com.lxl.www.aop.bank; import org.springframework.stereotype.Service; / * * * Description * / @ Service public class IcbcEnhanceFunctionOfBank implements EnhanceFunctionOfBank {/ * * * * finance function @param account */ @override public void financialanmanagement (Account account) {system.out.println (account.getName() + Add financial management function "); }}Copy the code

    This function can be dynamically added to the IcbcBank class by introducing it. Originally, IcbcBank only has the functions of saving and withdrawing money. In this way, you can increase the function of financial management. That’s the introduction.

  • Overall configuration class

    package com.lxl.www.aop.bank; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.EnableAspectJAutoProxy; @enableAspectJAutoProxy @ComponentScan(" com.lxL.www.aop.bank ") Public class BankMainConfig, works freely and freely To use AOP, you need to introduce AOP, introduced in the way of annotations used here.Copy the code
  • Main entry method

    package com.lxl.www.aop.bank; import com.lxl.www.aop.Calculate; import com.lxl.www.aop.MainConfig; import com.lxl.www.aop.ProgramCalculate; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class BankMainClass { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BankMainConfig.class); Account Account = new Account(" Account "); Bank bank = (Bank) ctx.getBean("icbcBank"); bank.save(account, 100); System.out.println(); EnhanceFunctionOfBank enhanceFunctionOfBank = (EnhanceFunctionOfBank) ctx.getBean("icbcBank"); enhanceFunctionOfBank.Financialanagement(account); }}Copy the code

    As above, the result of the run:

         

  • Note: it is a. Gradle configuration file. Typically, we import AspectJ jars into the parent project’s build.gradle. As shown below.

    Finally, we need to introduce it into the specified project

       

That’s the whole idea of AOP. Next, analyze the AOP source code.

See the next article