Spring Series 22: Spring AOP Concepts and Quick Start

Posted by jzhang1013 on Wed, 02 Mar 2022 18:23:36 +0100

Python WeChat Subscription Applet Course Video

https://edu.csdn.net/course/detail/36074

Python Actual Quantitative Transaction Finance System

https://edu.csdn.net/course/detail/35475

Contents of this article

  1. Spring AOP Meaning and Objectives
  2. Concepts related to AOP
  3. Declarative AOP Quick Start
  4. Programmatically create proxy objects

Spring AOP Meaning and Objectives

OOP:Object-oriented Programming Object-oriented programming, you're no longer familiar with it

AOP:Aspect-oriented Programming Face-Oriented Programming

Face-oriented programming complements object-oriented programming by providing another way to think about the structure of the program. The key unit of modularity in OOP is the class, while the key unit of modularity in AOP is the slice.

One of Spring's key components is the AOP framework. The Spring IoC container is independent of AOP, which provides a very powerful middleware solution to supplement Spring IoC. Mainly used in the following two areas:

  • Provides declarative services. The most important such service is declarative transaction management.
  • Let users implement custom facets and supplement their use of OOP with AOP.

Ability and objectives of Spring AOP

Spring AOP is implemented in pure Java. No special compilation process is required. Spring AOP does not require control over the class loader hierarchy and is therefore appropriate for servlet containers or application servers.

Spring AOP currently only supports method execution connection points (it is recommended that methods be executed on Spring bean s). Field interception is not implemented.

Spring AOP's AOP approach is different from most other AOP frameworks. Although Spring AOP is very strong, its purpose is not to provide the most complete AOP implementation, but rather to provide close integration between AOP implementation and Spring IoC to help solve common problems in enterprise applications. Therefore, the AOP functionality of the Spring Framework is often used in conjunction with the Spring IoC container. Aspects are configured using the common bean definition syntax (although this allows powerful "automatic proxy" capabilities), which is a key difference from other AOP implementations.

Spring AOP never strives to compete with AspectJ to provide a comprehensive AOP solution. Proxy-based frameworks such as Spring AOP and mature frameworks such as AspectJ are valuable, complementary rather than competitive. Spring seamlessly integrates Spring AOP and IoC with AspectJ to achieve all use of AOP in a consistent Spring-based application architecture. This integration will not affect the Spring AOP API or AOP Alliance API. Spring AOP remains backward compatible.

Concepts related to AOP

Get to know the core AOP concepts and terminology first for easy use later.

Cut Aspect

Modularization of concerns across multiple classes. Transaction management is a good example of crosscutting concerns in enterprise Java applications.

Connection point Join point

A point during program execution, such as method execution or exception handling. In Spring AOP, a connection point always represents a method execution.

Notify Advice

The action taken by the facet at a particular connection point. Different types such as pre-notification, surround notification, etc. Spring models notifications as interceptors and maintains a series of interceptors around connection points.

Tangent Pointcut

A predicate that matches a join point. Advice is associated with an entry point expression and runs at any connection point that matches the entry point (for example, executing a method with a specific name). The concept of join points matching entry point expressions is the core of AOP, and Spring uses AspectJ by default.

Introduction

Declare other methods or fields on the class. Spring AOP allows new interfaces and corresponding implementations to be introduced to any enhanced object. For example, you can use Introduction s to enable bean s to implement the IsModified interface to simplify caching.

Target object

Objects enhanced by one or more facets.

Proxy AOP proxy

An object created by the AOP framework to implement facet logic such as enhanced method execution. In the Spring Framework, the AOP proxy is either a JDK dynamic proxy or a CGLIB proxy.

Weaving in

Link facets to other application types or objects to create enhancement objects. This can be done at compile time, such as using the AspectJ compiler, at load time, or at run time. Like other pure Java AOP frameworks, Spring AOP performs weaving at run time.

Understand with a picture on the web.

The concept of connection points for point-of-entry matching is key to AOP, which distinguishes it from older technologies that provide interception only. The entry point makes the goal of enhancing Advice independent of the object-oriented hierarchy. You can apply surround notifications that provide declarative transaction management to a set of methods that span multiple objects, such as all business operations in the service layer.

quick get start

With annotations, the declarative Spring AOP is relatively simple to use, with the following main steps:

  1. Enable the auto-generation agent through @EnableAspectJAutoProxy;
  2. Define the facets through @Aspect and inject them into the Spring container;
  3. A tangent point can be defined in a slice by @Pointcut;
  4. Facets define notifications through notification annotations such as @Before
    • @Around Wrap Notification
    • @Before Pre-Notification
    • @After Final Notification
    • @AfterReturning returns notification
    • @AfterThrowing exception thrown notification
  5. Get bean s from containers to use

Take the non-invasive logging of class method execution as an example, and take a complete look at an AOP example.

  1. Introducing aspectjweaver dependencies
<dependency>
    <groupId>org.aspectjgroupId>
    <artifactId>aspectjweaverartifactId>
dependency>

  1. Enable @AspectJ annotation support
@Configuration
@ComponentScan
@EnableAspectJAutoProxy()
public class AppConfig {}

  1. Define target object
@Service
public class UserService {
    public void add(String name) {
        System.out.println("UserService add " + name);
    }
}

  1. Declare facets, tangents, and notifications
/**
 * Face Definition
 * Include the introduction of point-of-tangency notifications, etc.
 *
 * @author zfd
 * @version v1.0
 * @date 2022/1/29 13:33
 * @About me, follow the Java notes of the public crab for more technical series
 */
@Component
@Aspect // section
public class MyAspect {

    /**
 * Declare a starting point The expression here means: intercept all method execution of the UserService class
 */
    @Pointcut("execution(* com.crab.spring.aop.demo01.UserService.*(..))")
    public void pc(){}

    /**
 * Pre-notification, specify entry point
 * @param joinPoint
 */
    @Before("pc()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        System.out.println("I am a pre-notification!Start executing method:" + signature.getMethod().getName()); // Logging before method execution
    }
}

  1. Execute Target Method
public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AppConfig.class);
        IService bean = context.getBean(IService.class);
        System.out.println("bean Type of:" + bean.getClass());
        bean.add("xxx");
        context.close();
}

  1. Observe the output
bean Type of: class com.sun.proxy.$Proxy19
 I am a pre-notification!Start executing method: add
UserService add xxx

From the result, the proxy object was successfully intercepted and generated by the JDK dynamic proxy.
7. Analogue does not use AOP

The above effect is similar to the hard-coded writing below

@Service
public class UserService {
    public void add(String name) {
        System.out.println("I am a pre-notification!Start executing method:" + "add");
        System.out.println("UserService add " + name);
    }
}

Create proxy programmatically

The above Quick Start creates agents automatically, declaratively and annotated. The advantages are simplicity and convenience, while the disadvantages are that the user does not know the creation process and details. To learn more about how proxy is created in AOP, let's look at how proxy objects are created programmatically. The main class diagrams are as follows.

The interface or base class that is designed is the proxy configuration class AdvisedSupport, the factory class AopProxy Factory that creates the proxy, and the OpProxy. There are four ways to manually create proxy objects.

Mode 1: AdvisedSupport + AopProxyFactory mode

This method is the most original and basic, and other methods are based on it to package and simplify the creation. There are three main considerations for creating proxy objects:

  • Target object
  • Configuration of proxy mode
  • How to create a proxy object

Go directly to the case.

/**
 * Mode 1
 * Use AdvisedSupport + AopProxyFactory
 */
@Test
public void test1() {
    // 1. Target Object
    UserService target = new UserService();
    // 2 Agent Configuration Information
    AdvisedSupport advisedSupport = new AdvisedSupport();
    advisedSupport.setTarget(target); // Target object
    advisedSupport.addInterface(IService.class);// Agent's Interface
    advisedSupport.setProxyTargetClass(true);// , Force cglib proxy
    advisedSupport.addAdvice(new MethodBeforeAdvice() {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("Pre-notification, start execution method: " + method.getName());
        }
    });

    // 3 Create a factory for proxy objects
    DefaultAopProxyFactory proxyFactory = new DefaultAopProxyFactory();
    AopProxy aopProxy = proxyFactory.createAopProxy(advisedSupport);

    // 4 Get Proxy Objects
    Object proxy = aopProxy.getProxy();

    // 5 View agent information
    System.out.println("Type of proxy object:"+proxy.getClass());
    System.out.println("The parent class of the proxy object:"+proxy.getClass().getSuperclass());
    System.out.println("The proxy object implements the following interfaces:");
    for (Class itf : proxy.getClass().getInterfaces()) {
        System.out.println(itf);
    }

}

The code comments are clearer, so let's see the output.

Type of proxy object: class com.crab.spring.aop.demo01.UserService$$EnhancerBySpringCGLIB$$87584fdb
 The parent class of the proxy object: class com.crab.spring.aop.demo01.UserService
 The proxy object implements the following interfaces:
interface com.crab.spring.aop.demo01.IService
interface org.springframework.aop.SpringProxy
interface org.springframework.aop.framework.Advised
interface org.springframework.cglib.proxy.Factory

As a result:

  1. CGLIB proxy class mandatory
  2. Three additional interfaces, SpringProxy, Advised, Factory, are implemented by default, and the next two AOP source parsing articles will analyze how.

Mode 2: ProxyFactory

The original way required both agent configuration and agent factory creation classes to be operated on simultaneously, which was relatively complicated. The AopProxyFactory was introduced in ProxyFactory to simplify the creation process to a certain extent. Go directly to the case.

/**
 * Mode 2
 * Using ProxyFactory simplification, AopProxyFactory is combined in ProxyFactory
 */
@Test
public void test2() {
    // 1. Target Object
    UserService target = new UserService();
    // 2 Create a factory for proxy objects and proxy configuration information
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.setTarget(target);// Target object
    proxyFactory.addInterface(IService.class);// Implement Interface
    // Add Notification
    proxyFactory.addAdvice(new MethodBeforeAdvice() {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("Pre-notification, start execution method: " + method.getName());
        }
    });
    // 3 Get Proxy Objects
    Object proxy = proxyFactory.getProxy();

    // 5 Call method
    IService service = (IService) proxy;
    service.hello("xx");
}

The configuration of proxy information can be set directly through ProxyFactory. Look at the results.

Pre-notification, start execution method: hello
hello xx

Mode 3: AspectJProxyFactory

AspectJProxyFactory can create proxy objects in conjunction with the declared facets of @Aspect. Understanding this is helpful in understanding how @Aspect uses AOP declaratively, as detailed in our separate source analysis article.

Go directly to the case.

Definition of a facet, including points of tangency and notifications.

/**
 * @author zfd
 * @version v1.0
 * @date 2022/2/6 17:08
 * @About me, follow the Java notes of the public crab for more technical series
 */
@Aspect
public class MyAspect {

    /**
 * Declare a starting point The expression here means: intercept all method execution of the UserService class
 */
    @Pointcut("execution(* com.crab.spring.aop.demo01.UserService.*(..))")
    public void pc(){}

    /**
 * Pre-notification, specify entry point
 * @param joinPoint
 */
    @Before("pc()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        System.out.println("I am a pre-notification!Start executing method:" + signature.getMethod().getName());
    }
}

Use as follows

/**
 * Mode 3 uses AspectProxyFactory with @Aspect slicing
 */
@Test
public void test3(){
    // 1. Target Object
    UserService target = new UserService();
    // 2 Create a factory for proxy objects and proxy configuration information
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.setInterfaces(IService.class);
    // Set up cut faces with notifications and cut points
    proxyFactory.addAspect(MyAspect.class);

    // 3 Create proxy object
    IService proxy = proxyFactory.getProxy();

    // 4 Execution Target Method
    proxy.hello("xx");
}

give the result as follows

Pre-notification: execution(void com.crab.spring.aop.demo02.IService.hello(String))
hello xx

Mode 4: ProxyFactoryBean

ProxyFactoryBean is used to create proxy objects for specified bean s in the spring environment, not too many of them are needed. Go directly to the case.

Unlike the previous approach, this approach sets the target object and notification by specifying the bean name in the container.

package com.crab.spring.aop.demo01;

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

/**
 * ProxyFactoryBean Method to create proxy
 * @author zfd
 * @version v1.0
 * @date 2022/2/6 17:20
 * @About me, follow the Java notes of the public crab for more technical series
 */
@Configuration
public class AopProxyFactoryBeanConfig {

    // 1 Register the target object
    @Bean("userService")
    public UserService userService() {
        return new UserService();
    }

    // 2 Registration Notice
    @Bean("beforeAdvice")
    public MethodBeforeAdvice beforeAdvice() {
        return new MethodBeforeAdvice() {
            @Override
            public void before(Method method, Object[] args, Object target) throws Throwable {
                System.out.println("Pre-notification: " + method);
            }
        };
    }

    // 3 Register ProxyFactoryBean
    @Bean("userServiceProxy")
    public ProxyFactoryBean userServiceProxy() {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        // Set bean Name of Target Object
        proxyFactoryBean.setTargetName("userService");
        // Set bean Name for Interceptor
        proxyFactoryBean.setInterceptorNames("beforeAdvice");
        // Agent mode
// proxyFactoryBean.setProxyTargetClass(true);
        return proxyFactoryBean;
    }

}

Test procedures and results

    /**
 * Mode 4 uses ProxyFactoryBean
 */
    @Test
    public void test04() {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AopProxyFactoryBeanConfig.class);

        // Interface-oriented, supporting Jdk or CGLIB
        IService userService = (IService) context.getBean("userServiceProxy");

        // Class-oriented, only CGLIB, proxyFactoryBean is supported. SetProxyTargetClass (true)
// UserService userService = context.getBean("userServiceProxy", UserService.class);
        userService.hello("xxxx");

    }
// Result
 Pre-notification: public abstract void com.crab.spring.aop.demo01.IService.hello(java.lang.String)
hello xxxx

summary

This article mainly introduces the related concepts of Spring AOP, the introduction of declarative AOP, and four ways of creating proxies programmatically.

This source address: https://github.com/kongxubihai/pdf-spring-series/tree/main/spring-series-aop/src/main/java/com/crab/spring/aop/demo01

For knowledge sharing, please indicate the source. Learn first, reach first!

Topics: Python AI computer