AOP&SpringAOP&two kinds of dynamic proxy

1. What is AOP

Aspect-Oriented Programming (AOP) is a software development method designed to enhance code modularity, maintainability, and reusability by separating concerns (Concerns).

AOP is a continuation of OOP, a hot spot in software development, an important content in the Spring framework, and a derivative paradigm of functional programming. AOP can be used to isolate various parts of business logic, thereby reducing the coupling degree between various parts of business logic, improving the reusability of programs, and improving the efficiency of development at the same time.

Aspect programming makes code easier to manage and understand by abstracting Cross-Cutting Concerns from the main business logic.

As a Java engineer, you may often encounter problems that need to deal with multiple modules and classes, such as logging, transaction management, security authentication, etc. These concerns are usually separated from the main business logic, but they permeate the entire application. This is where aspect programming comes in.

The following are the key concepts and components of aspect programming:

  1. Aspect: An aspect is a modularization of concerns that encompasses a set of behaviors that span multiple classes. For example, a logging aspect could define logging before and after each method execution. Aspects themselves do not contain complete business logic, but define how to execute logic at points of concern.
  2. Join Point: A join point is a point where aspects can be inserted during application execution, usually method calls, object initialization, etc. Aspects can be executed at different timings such as before, after, or around a join point.
  3. Advice: Advice is the specific behavior performed by the aspect at the connection point, which can be method call, exception handling, surround logic, etc. The main notification types are pre-notification (Before), post-notification (After), surround notification (Around), return notification (AfterReturning) and exception notification (AfterThrowing).
  4. Pointcut: The pointcut defines which join points will trigger the notification of the aspect. It matches a set of join points by an expression or rule.
  5. Weaving: Weaving is the process of applying the aspect to the target code, that is, inserting the notification of the aspect into the connection point. Weaving can be performed at different stages such as compile time, class loading time, and runtime.
  6. Introduction: Introduction is a mechanism for dynamically adding new methods or properties to classes, allowing aspects to add new functionality to existing classes. This can be used to achieve an effect similar to multiple inheritance.

The advantage of aspect programming is that it provides a clear way to deal with cross-cutting concerns, separating them from the main business logic, thereby enhancing the maintainability and extensibility of the code. In Java, the implementation of aspect programming is mainly realized through the Spring AOP framework, which allows you to create and manage aspects through annotations or XML configuration. Using aspect programming, you can focus more on the core business logic without having to care too much about the handling of cross concerns.

2. Function and advantages

The role of AOP (Aspect-Oriented Programming, aspect-oriented programming) is to improve the modularity, maintainability and reusability of code by separating cross-cutting concerns (Cross-Cutting Concerns). It allows developers to separate cross-cutting concerns (such as logging, transactions, security, etc.) from the main business logic, making the code more clear, maintainable and extensible.

The advantages of AOP are reflected in the following aspects:

  1. Separation of Concerns: AOP makes code more modular by separating crosscutting concerns from the main business logic. This allows developers to focus on core business logic without having to repeat the same cross-concern code everywhere.
  2. Improves maintainability: By centralizing cross-cutting concerns, AOP makes code more maintainable. If you need to modify or extend the logic of a crosscutting concern, you only need to modify it in one place instead of multiple places.
  3. Reduce code redundancy: Since cross concerns are separated into aspects, different modules can share the same aspects, thereby avoiding code redundancy. For example, if multiple modules need to record logs, they can share a log aspect.
  4. Improves reusability: Aspects can be reused in different modules, which increases code reusability. When you need to use the same cross-concern logic in multiple projects, you only need to apply the aspect to different projects.
  5. Enhanced code flexibility: AOP allows dynamic weaving of aspects into object code without modifying the original code. This allows you to add or remove aspects as needed at runtime without having to modify the main business logic.
  6. Improve code readability: Separating cross-concerns from main business logic can make the main business logic clearer and more concise, thereby improving the readability and comprehension of the code.
  7. Facilitate team collaboration: By uniformly handling cross-cutting concerns, team members can share the same design and implementation patterns, thereby promoting team collaboration and development efficiency.

In summary, the role and its advantages are:

3. The underlying implementation of AOP

The underlying implementation of AOP is usually based on dynamic proxies and bytecode manipulation to weave aspect logic into object code at runtime.

In Java, there are two common underlying implementations of AOP: JDK-based dynamic proxy and CGLIB-based bytecode operations.

The basic principles of these two implementations are introduced below:

  1. JDK-based dynamic proxy: JDK dynamic proxy is implemented by using the java.lang.reflect.Proxy class and java.lang.reflect.InvocationHandler interface in the Java standard library . When an interface is proxied, the JDK dynamic proxy will create a proxy class that implements the interface at runtime, and each proxy method will be redirected to the call processing method of the object that implements the InvocationHandler interface. Invocations of proxy methods will be handled by call handler methods, allowing aspect logic to be executed before, after, or around invocations of target methods.
  2. Based on CGLIB bytecode operation: CGLIB (Code Generation Library) is a powerful bytecode operation library, which can generate subclasses and override parent class methods. In the AOP implementation based on CGLIB, the subclass of the target class will be dynamically generated at runtime, and the target method will be rewritten to weave the aspect logic. This approach works for classes that don't implement an interface. The underlying mechanism of CGLIB involves modifying the bytecode of the target class, so that the aspect logic can take effect in the method of the target class.

The general process of the underlying implementation of AOP is as follows:

  1. Define the aspect: define the notification method of the aspect, such as pre-notification, post-notification, surround notification, etc.
  2. Create a proxy: At runtime, the AOP framework will generate a proxy object based on the aspect definition and the target object.
  3. Weaving aspect logic: Weaving aspect logic into the method of the target object, so that the aspect logic can be executed before, after or around the target method call.
  4. Execute the proxy method: When the method of the proxy object is called, the notification method in the proxy object is actually called. Inside the notification method, the aspect logic is executed, and the target method is finally called.

It should be noted that although AOP implements the weaving of aspect logic through proxy technology, this weaving is done dynamically at runtime, so it may bring some performance overhead. The choice between using JDK dynamic proxies or CGLIB bytecode manipulation depends on factors such as whether the target class implements an interface.

In short, the underlying implementation of AOP is mainly based on dynamic proxy and bytecode operations. By weaving the aspect logic into the target code at runtime, the separation and processing of cross-concerns is realized.

4. Dynamic agent of JDK

The directory is as follows:

Target interface:

target:

Enhancement method:

Proxy tools:

package com.xzl.proxy.jdk;

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

/**
 * @author 逐梦苍穹
 * @date 2023/8/13 10:28
 */
public class ProxyUtil {
    public static Advice advice = new Advice();
    public static <T> T getProxy(T object) {
        return (T) Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        advice.before();
                        Object result = method.invoke(object, objects);
                        advice.afterReturning();
                        return result;
                    }
                });
    }
}

Test Methods:

Test Results:

5. Dynamic proxy of cglib

CGLIB (Code Generation Library) is a powerful bytecode manipulation library for generating and modifying the bytecode of Java classes at runtime. CGLIB dynamic proxy is a dynamic proxy mechanism based on bytecode operations. Unlike JDK dynamic proxy, it can proxy classes instead of just interfaces, and is suitable for classes that do not implement interfaces.

CGLIB is widely used in many Java frameworks and libraries, including Spring AOP.

The following is the basic principle and usage of CGLIB dynamic proxy:

  1. Generating subclasses: CGLIB dynamic proxies implement proxies by generating subclasses of the target class. This subclass will override the method of the target class and add aspect logic before and after the method call. This approach does not require the target class to implement the interface.
  2. Weaving aspect logic: CGLIB dynamic proxy weaves aspect logic into the generated subclass, so that the aspect logic can take effect in the method of the target class. Weaving can occur before, after, or around method calls.
  3. Create a proxy object: Use the Enhancer class provided by CGLIB to create a proxy object. Enhancer is a tool class used to generate instances of proxy classes.

The directory is as follows:

Enhancement method:

target:

Proxy tools:

package com.xzl.proxy.cglib; 

import org.springframework.cglib.proxy.Enhancer; 
import org.springframework.cglib.proxy.MethodInterceptor; 
import org.springframework.cglib.proxy.MethodProxy; 

import java.lang.reflect.Method ; 

/** 
 * @author 追梦天穹
 * @date 2023/8/13 10:28 
 */ 
public class ProxyUtil<T> { 
    //Create an enhancement method 
    public static Advice advice = new Advice(); 

    //Create a target object 
    public final T target; 

    //Initialize the target object 
    public ProxyUtil(T target){ 
        this.target = target; 
    } 

    public T getProxy(T t){  
        Enhancer enhancer = new Enhancer();//Create an enhancer
        enhancer.setSuperclass(t.getClass());//Set parent class 
        // set callback
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                advice.before();
                Object invoke = method.invoke(target,objects);
                advice.afterReturning();
                return invoke;
            }
        });
        //创建代理对象并返回
        return (T) enhancer.create();
    }
}

test:

result:

6. Summary

The differences between the two code implementations are:

Difference explained:

  1. The proxy library is different: the first piece of code uses the JDK dynamic proxy to create a proxy object through Proxy.newProxyInstance . The second piece of code uses CGLIB dynamic proxy to create a proxy object through Enhancer .
  2. The scope of application is different: JDK dynamic proxy can only proxy classes that implement interfaces, while CGLIB dynamic proxy can proxy any class, including classes that do not implement interfaces.
  3. Proxy objects are created in different ways: In JDK dynamic proxies, proxy objects are created through interface arrays. In CGLIB dynamic proxy, the proxy object is created by setting the parent class.
  4. Method interception methods are different: JDK dynamic proxy uses InvocationHandler to implement method interception. CGLIB dynamic proxy uses MethodInterceptor to implement method interception.
  5. Performance difference: In general, JDK dynamic proxies are faster than CGLIB dynamic proxies. CGLIB dynamic proxying involves generating subclasses of the target class, and uses more bytecode operations, which may introduce some performance overhead.

According to your needs and scenarios, you can choose a suitable dynamic proxy method. If the target class implements the interface, you can consider using the JDK dynamic proxy; if the target class does not implement the interface, you can consider using the CGLIB dynamic proxy.

Guess you like

Origin blog.csdn.net/qq_60735796/article/details/132261070