Spring learning summary (eight): AOP introduction

1. Introduction to AOP

1. Basic introduction to AOP

       Another important point in Spring is AOP. The full name of AOP is "Aspect Oriented Programming", that is, aspect-oriented programming, which isolates various parts of business logic, so that developers can concentrate on core business when writing business logic, thereby improving development efficiency. Simply put, it means adding new functions to the main function without modifying the source code.

       In traditional business processing code, we generally perform operations such as transaction processing and logging. In the past, through the use of OOP ideas, code reuse can be achieved in a combination or inheritance manner, but if a certain function (such as logging) is to be implemented, the same code will be scattered into each method at this time. When you want to close or modify a function, you must modify all related methods. This not only increases the workload of developers, but also increases the error rate of the code.

       AOP adopts a horizontal extraction mechanism to replace the repetitive code of the traditional vertical inheritance system . This horizontal extraction mechanism can encapsulate the common behaviors that affect multiple classes into a reusable module, and name it "Aspect", which is what we call the aspect. Aspects refer to those logics or responsibilities that are not related to the business, but are commonly called by business modules. They are encapsulated, thereby reducing the repetitive code in the system and reducing the coupling between modules, which is conducive to subsequent operability and Maintainable.

       For example: in a system, logging is a basic function, and all business processes in the system need to be logged. If the logging function is written into each business process, it will cause code redundancy and increase the difficulty of maintenance. Assuming that the logging logic changes at this time, the logging code in each business process needs to be modified, which is obviously not advisable. On the contrary, if the log record function is extracted as an independent module, when the business process requires it, the system automatically cuts the log record function into the business process, which makes maintenance much easier. And this formal AOP can achieve. As shown below:

 2. AOP related terms

the term description

Crosscutting concerns

Which methods are intercepted and what to do after interception, these concerns are called crosscutting concerns

Aspect

It is usually a class in which entry points and notifications can be defined. An application can have any number of aspects

JointPoint

The clear point in the program execution process, that is: the specific location of the business process that needs to be inserted into the aspect during the operation process, which is generally the call of the method. Because Spring only supports connection points of method types, connection points in Spring refer to methods that are intercepted. In fact, connection points can also be fields or constructors.

Advice

The specific implementation method of the aspect, what to do after intercepting the Joinpoint, that is, the content of the enhancement of the pointcut

Pointcut

It is the connection point with notification, which is used to define which connection points the notification should cut into. Different notifications usually need to cut into different connection points. In the program, it is mainly embodied in writing the entry point expression.

Weave (woven into)

Indicates cut-in, also known as weaving. The process of applying aspects to the target object to create a new proxy object. This process can occur during compilation, class loading, and runtime

Introduction

Under the premise of not modifying the code, the introduction can dynamically add some methods or fields to the class at runtime

Proxy

Represents the proxy object. An object that is dynamically created after the notification is applied to the target object. It can be simply understood that the proxy object is the object formed by the business logic function of the target object plus the cut surface. The AOP proxy in Spring can be a dynamic proxy for JDK or a CGLIB proxy. The former is based on interfaces and the latter is based on subclasses. 

Target Object

The object that contains the connection point is the object notified by one or more aspects. Also known as notified or proxied object

3. Types of notifications in AOP

 

Notification type description

Prior notice (Before)

Do enhancement processing before the target method is called, @Before only needs to specify the pointcut expression

Notification after return (AfterReturning)

After the target method is completed normally, it is enhanced. In addition to specifying the pointcut expression, @AfterReturning can also specify a return value parameter name returning, which represents the return value of the target method

Notification after an exception is thrown (AfterThrowing)

It is mainly used to handle unhandled exceptions in the program. In addition to specifying the pointcut expression, @AfterThrowing can also specify a throwing return value parameter name, which can be used to access the exception object thrown in the target method.

After notification (After)

Enhancement is done after the target method is completed, regardless of when the target method is successfully completed. @After can specify an entry point expression

Around Notification (Around)

Enhance processing before and after the completion of the target method, surround notification is the most important type of notification, such as transactions, logs, etc. are surround notifications

4. Entry point expression

Pointcut indicator is used to indicate the purpose of pointcut expression. Currently, there is only one connection point of execution method in Spring AOP. The format of the pointcut expression is as follows:

execution([visibility] return type [declaration type]. method name (parameter) [exception]), where [] is optional , others also support the use of wildcards:

      *: match all characters
      ..: generally used to match multiple packages, multiple parameters
      +: indicate the class and its subclasses

       Operators can also be used in pointcut expressions, such as: &&, ||,!

       Here is an example to illustrate the use of pointcut expressions:

       (1) Standard expression writing: public void com.yht.controller.UserController.findUser()

       (2) All wildcard writing: *..*.*(..)

       (3) Omit access modifier: void com.yht.controller.UserController.findUser()

       (4) The return value uses wildcard *: * com.yht.controller.UserController.findUser()

       (5) The package name uses wildcards*: * *.*.*.UserController.findUser() //If there are several levels of packages, write a few*

       (6) Use wildcard * for class name and method name: *..*.*()

       (7) Parameter list

       If there are parameters, add *——(*) to the () of the method

       With or without parameters: add in the () of the method..——(..)

       (8) Usually written: * com.yht.controller.UserController.*(..)

       For other introductions about pointcut expressions, please refer to the following blog:

       https://blog.51cto.com/lavasoft/172292

       https://www.cnblogs.com/sjqq/p/10241781.html

Second, the proxy mode in Spring

       Introduced earlier: The AOP proxy in Spring can be a dynamic proxy for JDK or a CGLIB proxy. The former is based on interfaces and the latter is based on subclasses. Next, implement these two proxy methods.

1. JDK dynamic proxy

       (1) Create the IOderDao interface and its subclass OrderDaoImpl.

public interface IOrderDao {
    void addOrder();
    void deleteOrder();
    void updateOrder();
    void searchOrder();
}
public class OrderDaoImpl implements IOrderDao {
    @Override
    public void addOrder() {
        System.out.println("添加订单");
    }

    @Override
    public void deleteOrder() {
        System.out.println("删除订单");
    }

    @Override
    public void updateOrder() {
        System.out.println("更新订单");
    }

    @Override
    public void searchOrder() {
        System.out.println("查询订单");
    }
}

       (2) Create an aspect class MyAspect

public class MyAspect {
    public void before(){
        System.out.println("方法执行之前");
    }
    public void after(){
        System.out.println("方法执行之后");
    }
}

       (3) Create a proxy class MyBeanFactory

public class MyBeanFactory {

    public static IOrderDao getBean() {
        // 准备目标类
        final IOrderDao customerDao = new OrderDaoImpl();
        // 创建切面类实例
        final MyAspect myAspect = new MyAspect();
        // 使用代理类,进行增强
        //Proxy 的 newProxyInstance() 方法的第一个参数是当前类的类加载器,第二参数是所创建实例的实现类的接口,第三个参数就是需要增强的方法
        return (IOrderDao) Proxy.newProxyInstance(
                MyBeanFactory.class.getClassLoader(),
                new Class[] { IOrderDao.class }, new InvocationHandler() {
                    public Object invoke(Object proxy, Method method,
                                         Object[] args) throws Throwable {
                        myAspect.before(); // 前增强
                        Object obj = method.invoke(customerDao, args);
                        myAspect.after(); // 后增强
                        return obj;
                    }
                });
    }
}

       (4) Perform a test.

    @Test
    public void test() {
        // 从工厂获得指定的内容(相当于spring获得,但此内容时代理对象)
        IOrderDao orderDao = MyBeanFactory.getBean();
        // 执行方法
        orderDao.updateOrder();
        System.out.println("=====================");
        orderDao.searchOrder();
    }

       The results are as follows:

 

2. cglib dynamic proxy

       (1) Import the jar package

    <!-- https://mvnrepository.com/artifact/cglib/cglib-nodep -->
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib-nodep</artifactId>
      <version>3.1</version>
    </dependency>

       (2) Create the target class Goods

public class Goods{

    public void addGoods() {
        System.out.println("添加货物");
    }

    public void deleteGoods() {
        System.out.println("删除货物");
    }

    public void updateGoods() {
        System.out.println("更新货物");
    }

    public void searchGoods() {
        System.out.println("查询货物");
    }
}

       (3) Create a proxy class GoodsBeanFactory

public class GoodsBeanFactory {
    public static Goods getBean() {
        // 准备目标类
        final Goods goodsDao = new Goods();
        // 创建切面类实例
        final MyAspect myAspect = new MyAspect();
        // 生成代理类,CGLIB在运行时,生成指定对象的子类,增强
        Enhancer enhancer = new Enhancer();
        // 确定需要增强的类
        enhancer.setSuperclass(goodsDao.getClass());
        // 添加回调函数
        enhancer.setCallback(new MethodInterceptor() {
            // intercept 相当于 jdk invoke,前三个参数与 jdk invoke—致
            @Override
            public Object intercept(Object proxy, Method method, Object[] args,
                                    MethodProxy methodProxy) throws Throwable {
                myAspect.before(); // 前增强
                Object obj = method.invoke(goodsDao, args); // 目标方法执行
                myAspect.after(); // 后增强
                return obj;
            }
        });
        // 创建代理类
        Goods goodsDaoProxy = (Goods) enhancer.create();
        return goodsDaoProxy;
    }
}

       (4) Test

    @Test
    public void testGoods() {
        // 从工厂获得指定的内容(相当于spring获得,但此内容时代理对象)
        Goods goods = GoodsBeanFactory.getBean();
        // 执行方法
        goods.deleteGoods();
        System.out.println("=====================");
        goods.searchGoods();
    }

       The results are as follows:

Guess you like

Origin blog.csdn.net/weixin_47382783/article/details/112802200