The best article in Spring - AOP container

Posted by betazoid on Wed, 27 Oct 2021 01:49:04 +0200

1, Concept of AOP

⭐ What is AOP

  1. Aspect oriented programming (aspect oriented), AOP can isolate each part of business logic, reduce the coupling between each part of business logic, improve the reusability of program, and improve the efficiency of development.
  2. That is, add new functions to the main functions without modifying the source code.

⭐ The underlying AOP uses dynamic proxies

  1. The first case is the case where there is an interface. JDK dynamic proxy is used

Create interfaces to implement class proxy objects and enhance class methods.

  1. The second case is that there is no interface. CGLIB dynamic proxy is used

Create proxy objects of subclasses and enhance the methods of classes.

1.1 AOP (JDK dynamic agent)

  1. Use JDK dynamic Proxy and use the methods in the Proxy class to create Proxy objects

Call the newProxyInstance method.
The method has three parameters:
First: class loader.
Second: the class where the enhancement method is located. The interface implemented by this class supports multiple interfaces.
Third: implement this interface InvocationHandler, create proxy objects, and write enhanced methods.

  1. Write JDK dynamic agent code

(1) Create interfaces and define methods

package com.jzq.spring5.mapper;
	public interface UserMapper {
	public int add(int a, int b);
	public String update(String id);
}

(2) Create interface implementation classes and implement methods

package com.jzq.spring5.mapper;
public class UserMapperImpl implements UserMapper {
    @Override
    public int add(int a, int b) {
        System.out.println("add Method is executed...");
        return a + b;
    }

    @Override
    public String update(String id) {
        System.out.println("update Method is executed");
        return "id:" + id;
    }
}

(3) Creating interface Proxy objects using Proxy classes

package com.jzq.spring5.mapper;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class JDKProxy {
    public static void main(String[] args) {
        // Create interface implementation class proxy object
        Class[] interfaces = {UserMapper.class};

        // The object can be obtained by IOC control inversion, but I directly new here
        UserMapperImpl userMapperImpl = new UserMapperImpl();

        // AOP here is to add logic to the code without modifying the source code

        UserMapper userMapper = (UserMapper)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserMapperProxy(userMapperImpl));
        int result = userMapper.add(1,2);
        String res = userMapper.update("EDDD-DSSS");
        System.out.println("result:" + result);
    }
}


// Create proxy object code
class UserMapperProxy implements InvocationHandler {
    // 1. Transfer the created proxy object to the user
    // Parametric construction

    private Object object;
    public UserMapperProxy(Object object) {
        this.object = object;
    }

    // Write enhanced logic
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // Before method
        System.out.println("Before method execution: " + method.getName() + "Parameters passed" + Arrays.toString(args));

        // Enhanced method execution
        Object res = method.invoke(object, args);

        // After method
        System.out.println("After method execution.."+object);

        // Return res, enhanced method
        return res;
    }
}

1.2 AOP (terminology)

⭐ Connection point

Which methods in the class can be enhanced are called join points.

⭐ breakthrough point

The method that is actually really enhanced is called the pointcut.

⭐ Notification (enhanced)

(1) The logical part of the actual enhancement is called notification (enhancement)
(2) There are many types of notifications: pre notification, post notification, surround notification, exception notification, and final notification

⭐ Section (action)

(1) Apply notifications to pointcut procedures

1.3 AOP operation (preparation)

⭐ spring frameworks generally implement AOP operations based on AspectJ

AspectJ is not a part of spring. It is an independent AOP framework. Generally, AspectJ and spring framework are used together for AOP operation.

⭐ Pointcut expression

1.4 AOP operation (AspectJ annotation)

⭐ 1. Create a class and define methods in the class

package com.jzq.spring5.aopseven;

import org.springframework.stereotype.Component;

public class User {
    public void add() {
        System.out.println("Added a user");
    }
}

⭐ 2. Create enhanced classes (write enhanced logic)
(1) In the enhanced class, create methods so that different methods represent different notifications (enhanced).

package com.jzq.spring5.aopseven;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

public class UserProxy {
    public void before(){
        System.out.println("Before advice ");
    }

}

⭐ 3. Configure notifications
(1) In the spring configuration file, turn on annotation scanning (IOC).

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--  Enable annotation scanning  -->
    <context:component-scan base-package="com.jzq.spring5.aopseven"></context:component-scan>

</beans>

(2) Create User and UserProxy using annotations. Add the annotation @ Aspect above the enhanced class UserProxy.

Annotation development, IOC control, inversion knowledge

User class configuration
//IOC notes
@Component: (XML configured package scanning < context: component scan >)

package com.jzq.spring5.aopseven;

import org.springframework.stereotype.Component;


//IOC notes
@Component  
public class User {
    public void add() {
        System.out.println("Added a user");
    }
}

@Component: IOC control inversion (xml is configured with package scanning < context: component scan >)
@Aspect: generate proxy object (configure < AOP: AspectJ AutoProxy / > in xml)

package com.jzq.spring5.aopseven;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

//IOC notes
@Component
// Generate proxy object
@Aspect
public class UserProxy {

    // Before advice 
    // @Before annotation indicates pre notification
    @Before(value = "execution(* com.jzq.spring5.aopseven.User.add(..))")
    public void before(){
        System.out.println("Before advice ");
    }
}

(3) Turn on the build proxy object in the spring configuration file.

Open Aspect to generate a proxy object, and he will look for the class with @ Aspect annotation
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


<!--  Enable annotation scanning  -->
<context:component-scan base-package="com.jzq.spring5.aopseven"></context:component-scan>

<!--  open Aspect Generate proxy object, He will look for@Aspect Annotated class  -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

⭐ 4. Configure different types of notifications (enhanced)

(1) In the enhanced class, the notification type annotation is added on the notification method, and the pointcut expression configuration is used.

⭐⭐ Several notification configurations
Pre notification configuration @ Before (value = "execution(* com.jzq.spring5.aopseven.User.add(...))
Post notification (return notification): @ AfterReturning(value = "execution(* com.jzq.spring5.aopseven.User.add(...))")
Final notification: @ After(value = "execution(* com.jzq.spring5.aopseven.User.add(...))")
Exception notification: @ AfterThrowing(value = "execution(* com.jzq.spring5.aopseven.User.add(...))")
Surround notification: @ Around(value = "execution(* com.jzq.spring5.aopseven.User.add(...))") / / this needs to be referred to ProceedingJoinPoint

(2) Execution sequence under normal conditions

Notify Around before wrapping
Pre notification Before
Added one
Notify Around after surround
Final notification After
Post notification AfterReturning

(3) Execution sequence in case of exception

Notify Around before wrapping
Pre notification Before
Final notification After
Exception notification AfterThrowing

package com.jzq.spring5.aopseven;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

//IOC notes
@Component
// Generate proxy object
@Aspect
public class UserProxy {

    // Before advice 
    // @Before annotation indicates pre notification
    @Before(value = "execution(* com.jzq.spring5.aopseven.User.add(..))")
    public void before() {
        System.out.println("Before advice ");
    }

    //Post notification (return notification)
    @AfterReturning(value = "execution(* com.jzq.spring5.aopseven.User.add(..))")
    public void afterReturning() {
        System.out.println("Post notification");
    }

    // Final notice
    @After(value = "execution(* com.jzq.spring5.aopseven.User.add(..))")
    public void after() {
        System.out.println("Final notice");
    }

    // Exception notification
    @AfterThrowing(value = "execution(* com.jzq.spring5.aopseven.User.add(..))")
    public void afterThrowing() {
        System.out.println("Exception notification");
    }

    // Around Advice 
    @Around(value = "execution(* com.jzq.spring5.aopseven.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("Pre surround notification");

        // Enhanced method execution
        proceedingJoinPoint.proceed();

        System.out.println("Post surround notification");
    }

}

1.5 AOP (same pointcut extraction)

Comments: @ Pointcut(value = "execution(* com.jzq.spring5.aopseven.User.add(...))")
It refers to that when other pointcuts specify expressions, they can be specified through a function

// Fairy pointcut extraction
    @Pointcut(value = "execution(* com.jzq.spring5.aopseven.User.add(..))")
    public void pointdemo() {
        // This function can be used to specify expressions for other pointcuts
    }

1.6 AOP (when multiple enhancement classes enhance the same method, set the priority of the enhancement class)

Through annotation @ Order(-1), the smaller the value, the higher the priority

package com.jzq.spring5.aopseven;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(-2)
public class PersonProxy {


    @Before(value = "execution(* com.jzq.spring5.aopseven.User.add(..))")
    public void before() {
        System.out.println("person Pre cut");
    }

}

1.7 full annotation development AOP

No xml configuration file is required, but a configuration class is required
@EnableAspectJAutoProxy(proxyTargetClass = true) indicates that Aspect is enabled

package com.jzq.spring5.config;


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = {"com.jzq.spring5.aopseven"})

// ==< AOP: AspectJ AutoProxy > < / AOP: AspectJ AutoProxy > <! -- turn on Aspect to generate proxy objects, and he will look for classes with @ Aspect annotation -- >
@EnableAspectJAutoProxy(proxyTargetClass = true)

public class ConfigPrr {
}

1.8 AOP (configuration file implementation)

  1. Create enhanced class (... Proxy) and enhanced class
  2. Create two beans (class objects) in the spring configuration file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                          ">
    <!--  IOC Configuration object  -->
    <bean id="book" class="com.jzq.spring5.aopxml.Book"></bean>
    <bean id="bookPorxy" class="com.jzq.spring5.aopxml.BookProxy"></bean>
</beans>
  1. Configuring pointcuts in the spring configuration file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                          ">


    <!--  IOC Configuration object  -->
    <bean id="book" class="com.jzq.spring5.aopxml.Book"></bean>
    <bean id="bookPorxy" class="com.jzq.spring5.aopxml.BookProxy"></bean>

    <!--  AOP Configuration enhancement -->
    <aop:config>
        <!--  breakthrough point  -->
        <aop:pointcut id="p" expression="execution(* com.jzq.spring5.aopxml.Book.add(..))"/>

        <!--  Configure section(The process of applying notifications to pointcuts)  -->
        <aop:aspect ref="bookPorxy">
            <!--  Enhance the role in specific methods  -->
            <aop:before method="before" pointcut-ref="p"></aop:before>
        </aop:aspect>
    </aop:config>
</beans>

Topics: Java Spring Container