Principle analysis of Spring AOP -- creating proxy object

Posted by genesysmedia on Thu, 27 Jan 2022 04:49:46 +0100

catalogue

1, Introduction

2, AOP create proxy object process

3, Summary

1, Introduction

In the previous article, we introduced some things that AnnotationAwareAspectJAutoProxyCreator does behind the implementation of the instantiawarebeanpostprocessor interface. The most important thing is to parse the aspect, wrap the notification method corresponding to the aspect into an Advisor enhancer, and store it in the cache, which is convenient for later use when creating proxy objects.

At the class level, we can see that AnnotationAwareAspectJAutoProxyCreator inherits AbstractAutoProxyCreator and implements the bean's post processor BeanPostProcessor interface. After implementing BeanPostProcessor, Spring will execute the postProcessAfterInitialization() method after initialization when loading the bean, The postProcessAfterInitialization method is mainly to create the proxy object through the enhancer created earlier.

2, AOP create proxy object process

After the Spring container is started, each bean will go through two methods: postProcessBeforeInitialization() and postProcessAfterInitialization() before and after initialization. Next, we will focus on the implementation of these two methods in the AbstractAutoProxyCreator class related to AOP.

  • postProcessBeforeInitialization()
public Object postProcessBeforeInitialization(Object bean, String beanName) {
    return bean;
}

postProcessAfterInitialization() is not implemented in AnnotationAwareAspectJAutoProxyCreator, but in its parent class AbstractAutoProxyCreator. Let's take a look at the source code of the AbstractAutoProxyCreator#postProcessAfterInitialization() method.

  • postProcessAfterInitialization()

After initialization, all Spring managed beans will call the postProcessAfterInitialization() method of all beanpostprocessors, and then call the wrapIfNecessary method.

// AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    // If the bean is not empty, judge whether proxy is needed. If proxy is needed, it will be wrapped
    if (bean != null) {
        // Get cache key:
        // a. If the beanName is not empty, it will also determine whether it is a FactoryBean. If it is a FactoryBean, use "& + beanName" as the cache key, otherwise directly use beanName;
        // b. If beanName is empty, directly use beanClass as the cache key;
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // If necessary, carry out specific packaging
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    // If the bean is empty, it returns directly
    return bean;
}

The core logic of AOP generation agent is in wrapIfNecessary() method, and its source code is as follows:

// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary
// If the bean meets the conditions of being proxied, it will be proxied
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 1. If the current beanName (i.e. processed) already exists in the targetSourcedBeans cache, the current bean will be returned directly
    // private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }

    // 2. If it exists in the advisedBeans cache and value is false, the current bean will be returned directly
    // 	private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }

    // 3. If the current bean class is an infrastructure class (Advice, Pointcut, Advisor, aopinstructurebean) or needs to skip the proxy of the current bean, if one of the conditions is met, the current bean will be returned directly
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        // Add the current bean to the advisedBeans cache, and the value is false
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // If the notification is included, create the proxy object corresponding to the current bean

    // 4. Get the advice and Advisors (enhancement method) corresponding to the current bean
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

    // 	If specificInterceptors is not null (there is an enhancement method), you need to create an agent for the enhancement
    if (specificInterceptors != DO_NOT_PROXY) {
        // Mark that the current bean has been processed, that is, save the current bean in the adviedbeans cache, and the value is true
        this.advisedBeans.put(cacheKey, Boolean.TRUE);

        // 5. Create proxy object
        // new SingletonTargetSource(bean): the target object, which is convenient to obtain the original object being proxied
        Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

        // 6. After creating the proxy, put the class of cachekey - > proxy class into the proxyTypes cache
        // private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        // Return the enhanced proxy object of the current bean to the container. In the future, the proxy object of the bean will be obtained in the container. When the target method is executed, the proxy object will execute the process of notifying the method
        return proxy;
    }

    // 7. Add the current bean into the advisedBeans cache, and the value is false
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

Execution process of wrapIfNecessary() method:

  1. Judge whether the current beanName (i.e. processed) exists in the targetSourcedBeans cache. If it already exists, it will directly return the current bean;
  2. If it exists in the advisedBeans cache and value is false, the current bean will be returned directly;
  3. If the current bean class is an infrastructure class (Advice, Pointcut, Advisor, aopinstructurebean) or needs to skip the proxy of the current bean, if one of the conditions is met, the current bean will be returned directly;
  4. Obtain the advice and Advisors (enhancement method) corresponding to the current bean;
  5. Create proxy object;
  6. After creating the proxy, put the class of cachekey - > proxy class into the proxyTypes cache;
  7. Add the current bean into the advisedBeans cache, and the value is false;

There are three main core logics:

(1) , isinstructureclass (bean. Getclass()) 𞓜 shouldskip (bean. Getclass(), beanname)

Judge whether the current bean class is an infrastructure class (Advice, Pointcut, Advisor, aopinstructurebean) or need to skip the proxy of the current bean. If one of the conditions is met, the current bean will be returned directly.

This part of the code has been analyzed in detail in the previous article, and the analysis will not be repeated here.

(2) , getAdvicesAndAdvisorsForBean()

Get the advice and Advisors (enhancement method) corresponding to the current bean. We trace the source code of the getAdvicesAndAdvisorsForBean() method:

// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
    Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

    // Obtain the qualified Advisor enhancer
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);

    // If there is no corresponding intensifier, null is returned
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }

    // If the intensifier is not empty, the Advisor array is returned
    return advisors.toArray();
}

It can be seen that getAdvicesAndAdvisorsForBean() internally obtains the qualified Advisor enhancer by calling the findEligibleAdvisors() method. If there is no corresponding enhancer, it will directly return null. Otherwise, it will return the obtained Advisor array.

// Find the right enhancer object
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 1. Obtain all candidate Advisor enhancers (notification method)
    List<Advisor> candidateAdvisors = findCandidateAdvisors();

    // 2. Select the enhancers that can be applied to the current bean from the set of candidate Advisor enhancers (find out which notification methods need to cut into the current bean method)
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

    // 3.Spring provides an extension point for subclasses to add additional Advisor enhancers. The default is null implementation
    extendAdvisors(eligibleAdvisors);

    // 4. Sort the enhancers that can be really applied. Spring allows subclasses to override the sortAdvisors() method to define the sorting strategy
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }

    // 5. Return to the set of Advisor enhancers that can be really applied
    return eligibleAdvisors;
}

Execution process of findEligibleAdvisors() method:

  1. Obtain all candidate Advisor enhancers (notification method);
  2. Select the enhancers that can be applied to the current bean from the candidate Advisor enhancer set (find out which notification methods need to cut into the current bean method);
  3. Spring provides an extension point for subclasses to add additional Advisor enhancers. The default is empty implementation;
  4. Sort the enhancers that can be applied. Spring allows subclasses to override the sortAdvisors() method to define the sorting strategy;
  5. Return the set of Advisor enhancers that can be really applied;

First, let's take a look at how to obtain all candidate Advisor enhancers (notification methods), specifically in the findcandidedadvisors () method. Similarly, it has been analyzed in detail in the previous article. The analysis will not be repeated here. You can check the previous chapter.

After obtaining all candidate Advisor enhancers (notification methods), you need to filter out the enhancers that can be really applied to the current bean. The specific logic is in the findadvisors thatcanapply() method:

// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    // Record the bean currently being proxied and save it in ThreadLocal
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);

    try {
        // Find the appropriate enhancer from the candidate notifiers (which can be applied to the current bean)
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    } finally {
        // Empty ThreadLocal
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

The core logic is in the findadvisors thatcanapply() method:

// org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    // If the candidate intensifier is null, it returns null directly
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }

    // Used to store qualified enhancer collection objects
    List<Advisor> eligibleAdvisors = new ArrayList<>();

    // Loop all candidate enhancer objects to determine whether the enhancer object implements the introduction advisor interface && and whether it can be applied
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }

    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
        // It has been processed before and needs to be skipped
        if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
        }

        // canApply(): really judge whether the current enhancer can be applied to the current bean
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

The main process of findadvisors thatcanapply() method is to loop through all candidate enhancers, candidedadvisors, and then call the canApply() method one by one to determine whether the current enhancer can be applied to the current bean.

// org.springframework.aop.support.AopUtils.canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    if (advisor instanceof IntroductionAdvisor) {
        // Introduction advisor type intensifier processing
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    else if (advisor instanceof PointcutAdvisor) {
        // Processing of enhancer of PointcutAdvisor type
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        // It doesn't have a pointcut so we assume it applies.
        return true;
    }
}

The logic of canApply() method is relatively clear. It processes the intensifiers of IntroductionAdvisor type and PointcutAdvisor type respectively. Here, we take the intensifier processing of PointcutAdvisor type as an example to see how to match:

// org.springframework.aop.support.AopUtils.canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    Assert.notNull(pc, "Pointcut must not be null");
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;
    }

    // Get the MethodMatcher method matcher object through the tangent point
    MethodMatcher methodMatcher = pc.getMethodMatcher();
    if (methodMatcher == MethodMatcher.TRUE) {
        // No need to iterate the methods if we're matching any method anyway...
        return true;
    }

    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }

    // A collection that holds the target object class
    Set<Class<?>> classes = new LinkedHashSet<>();

    // Judge whether the target class object is the class object of the proxy
    if (!Proxy.isProxyClass(targetClass)) {
        classes.add(ClassUtils.getUserClass(targetClass));
    }

    // Get the class object of the interface implemented by the target object, and then add it to the classes collection
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

    // Traverse all class objects
    for (Class<?> clazz : classes) {
        // Get all methods through reflection
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        // Cycle all methods
        for (Method method : methods) {
            // Through methodmatcher Matches. If true is returned, it indicates a match and is added to the collection eligibleAdvisors
            if (introductionAwareMethodMatcher != null ?
                introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    return false;
}

So far, we have screened out the enhancers that can really be applied to the current bean from the set of candidate Advisor enhancers, and Spring also provides an extension point to allow us to add additional enhancers, which can be realized by rewriting the extendAdvisors() method. Finally, after sorting the enhancers that can be applied, all the enhancers that can be applied to the current bean are returned. After obtaining the enhanced method of the current bean, call the createProxy method to create a proxy.

(3) , createProxy()

The createProxy() method is where the proxy object is actually created.

Spring uses the factory mode to implement it. Let's take a brief look at the relevant class diagram:

Next, let's look at the specific source code:

// Create an AOP proxy for a given bean
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    // Create ProxyFactory proxy factory
    ProxyFactory proxyFactory = new ProxyFactory();
    // Copy the corresponding configuration from the current object
    proxyFactory.copyFrom(this);

    // Check the proxyTargetClass attribute to determine whether to use Cglib dynamic proxy or JDK dynamic proxy for a given bean (for example, @ EnableAspectJAutoProxy(proxyTargetClass = true): true means to force the use of Cglib dynamic proxy)
    if (!proxyFactory.isProxyTargetClass()) {
        // Check whether the value of the preserveTargetClass attribute is true, and judge whether beanClass is a Cglib dynamic agent or a JDK dynamic agent
        if (shouldProxyTargetClass(beanClass, beanName)) {
            // If it is a class based proxy, assign proxyTargetClass to true
            proxyFactory.setProxyTargetClass(true);
        } else {
            // Evaluate the proxy interface of the current bean
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    // Convert the interceptor chain corresponding to the current bean into an Advisor enhancer
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    // Add advisors to proxy factory proxyFactory
    proxyFactory.addAdvisors(advisors);
    // Set the proxied class object (i.e. target object)
    proxyFactory.setTargetSource(targetSource);
    // Customize ProxyFactory, which is an extension point provided by Spring and left to subclass implementation
    customizeProxyFactory(proxyFactory);
    // Specifies whether to allow modification of notifications after proxyFactory is configured. The default value is false
    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    // Get the proxy object through getProxy()
    return proxyFactory.getProxy(getProxyClassLoader());
}

General processing flow of createProxy() method:

  1. Create a ProxyFactory proxy factory object and copy the corresponding configuration from the current object;
  2. Convert the interceptor chain corresponding to the current bean into an Advisor enhancer array;
  3. Add the currently acquired enhancer advisors to the proxy factory proxyFactory;
  4. Set the proxy target object of the current proxy factory as the current bean;
  5. Create a dynamic agent factory of JDK or CGLIB according to the configuration, and then return to proxyFactory;
  6. Get the proxy object through getProxy();

Here, we mainly analyze the process of getProxy() obtaining proxy objects.

public Object getProxy(@Nullable ClassLoader classLoader) {
    // Create AopProxy
    // Get the proxy object instance through getProxy()
    return createAopProxy().getProxy(classLoader);
}

The getProxy() method first creates the AopProxy object, and returns the JdkDynamicAopProxy or ObjenesisCglibAopProxy object according to whether the proxy object implements the interface or not.

// org.springframework.aop.framework.AopProxyFactory.createAopProxy
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;

// org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    // Determine whether to use JDK dynamic agent or Cglib agent

    // config. Iseptimize(): controls whether agents created through cglib use aggressive optimization strategies
    // config.isProxyTargetClass(): false by default. When set to true, cglib proxy is forced to be used;
    // Hasnousersuppliedproxyinterfaces (config): whether there is a proxy interface in config or only one interface in spring proxy
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: " +
                                         "Either an interface or a target is required for proxy creation.");
        }
        // If the target class of the proxy is an interface or the targetClass is a Proxy class, JDK dynamic proxy is used
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        // In other cases, Cglib dynamic agent is used
        return new ObjenesisCglibAopProxy(config);
    } else {
        // If the above conditions are not met, the JDK dynamic proxy is used
        return new JdkDynamicAopProxy(config);
    }
}

We know whether to use JDK dynamic proxy or Cglib dynamic proxy through the createAopProxy() method, and then we use aopproxy The getproxy () method returns the proxy object.

  • JDK dynamic proxy: jdkdynamicaopproxy getProxy()
// org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }
    // 1. Get the interface to be implemented by the proxy class
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    // 2. Check whether the interface obtained in the previous step defines the equals() or hashcode() methods
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // 3, the incoming class is implemented through classLoader, interface and InvocationHandler, and then calls Proxy.. Newproxyinstance generates a specific proxy object (JDK dynamic proxy)
    // public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    // The JdkDynamicAopProxy class implements the InvocationHandler interface, so the method calls of the generated proxy object will be delegated to InvocationHandler In the invoke() method
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

JDK dynamic proxy Newproxyinstance (classloader loader, class <? > [] interfaces, invocationhandler h) generates a proxy object. Finally, when the class of dynamic proxy through JDK is called, it will execute the JdkDynamicAopProxy#invoke method.

This is the JDK dynamic proxy.

  • Cglib dynamic proxy: cglibaopproxy getProxy()
// org.springframework.aop.framework.CglibAopProxy.getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
    }

    try {
        // Gets the type of the proxied class
        Class<?> rootClass = this.advised.getTargetClass();
        Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

        Class<?> proxySuperClass = rootClass;

        // If rootClass has been represented by Cglib, get the parent class of rootClass and assign it to proxySuperClass
        if (ClassUtils.isCglibProxyClass(rootClass)) {
            proxySuperClass = rootClass.getSuperclass();
            Class<?>[] additionalInterfaces = rootClass.getInterfaces();
            for (Class<?> additionalInterface : additionalInterfaces) {
                this.advised.addInterface(additionalInterface);
            }
        }

        // Verify proxySuperClass, mainly to verify whether the method is modified with final and the package visible method across ClassLoader. If so, write the warning to the log
        validateClassIfNecessary(proxySuperClass, classLoader);

        // Configure CGLIB Enhancer...

        // Create and configure CGLIB Enhancer
        Enhancer enhancer = createEnhancer();
        if (classLoader != null) {
            // Set class loader
            enhancer.setClassLoader(classLoader);
            if (classLoader instanceof SmartClassLoader &&
                ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }
        // Parent interface type
        enhancer.setSuperclass(proxySuperClass);
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

        // Get all interceptors to callback
        Callback[] callbacks = getCallbacks(rootClass);
        Class<?>[] types = new Class<?>[callbacks.length];
        for (int x = 0; x < types.length; x++) {
            types[x] = callbacks[x].getClass();
        }
        // fixedInterceptorMap only populated at this point, after getCallbacks call above
        enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);

        // Via enhancer Create() generates the proxy class, creates the proxy instance, and returns the proxy instance
        return createProxyClassAndInstance(enhancer, callbacks);
    }
    catch (CodeGenerationException | IllegalArgumentException ex) {
        throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                                     ": Common causes of this problem include using a final class or a non-visible class",
                                     ex);
    }
    catch (Throwable ex) {
        // TargetSource.getTarget() failed
        throw new AopConfigException("Unexpected AOP exception", ex);
    }
}

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
    enhancer.setInterceptDuringConstruction(false);
    enhancer.setCallbacks(callbacks);
    return (this.constructorArgs != null && this.constructorArgTypes != null ?
            enhancer.create(this.constructorArgTypes, this.constructorArgs) :
            enhancer.create());
}

As mentioned above, the CGLIB dynamic proxy is implemented through Enhancer object and the bottom layer modifies the bytecode with the help of ASM bytecode editing framework. Finally, when the class proxied by CGLIB is called, it will execute the dynamicadispedeinterceptor #intercept method.

3, Summary

Similarly, finally, the whole process of creating proxy objects in Spring is summarized through a figure:

So far, the process of AOP agent generation has been introduced, and the whole process is still relatively complex. Readers, read it more and Debug it several times. Anyway, I've read it for almost two weeks, and I can only say I know a little.

 

Topics: Spring Dynamic Proxy