• In the previous Article, Spring AOP In Use: Getting Familiar with Pre-advice, Post-advice, Return Advice, Exception Advice, and Understanding its features, we learned how to use AOP and some of its features, while raising the following questions:

    1. How does the source code bind the various notifications we define to target methods

    2. Policies generated by AOP proxy objects

    3. What is the execution order of our AOP proxy objects

    Let’s continue with the test case from the previous article and look at all three points from the source perspective. No more nonsense, just get to work!

How do we bind the various notifications we define to target methods in the source code

  • What would you do if you were to implement AOP on your own? (3 minutes later….) Whichever way you implement it, you will end up using the proxy design pattern. There is no doubt that we use proxy objects to enhance the target object, and then we can perform many custom actions before or after the execution of the target object’s methods: such as pre-setting, post-setting, and so on. So how does Spring implement AOP? As you all know, before you can use Spring’s AOP, you need to define aspects, pointcuts, and advice so that Spring knows which destination (pointcuts) to logically enhance (advice). Next, let’s take a look at what Spring does.

1.1 Meaning of the EnableAspectJAutoProxy annotation

  • When using Spring, we typically add the @enableAspectJAutoProxy annotation to the configuration class to enable aop functionality for the project. So what does this annotation mainly do in Spring? This with the spring * * @ Import extension points related to (if you are not familiar with, you can see me before spring series related articles), it is mainly to the spring container Import AspectJAutoProxyRegistrar * * bean, that the bean to do what? Take a look at the image below:

    As shown in the figure: The main is to add a spring container type for AnnotationAwareAspectJAutoProxyCreator, Name org. Springframework. Aop. Config. The internalAutoProxyCreator beanDefinition (due to the bean’s name is too long, subsequent unified called aopProxyCreator). Second, the properties of the corresponding fields of the aopProxyCreator Bean are populated based on the proxyTargetClass and exposeProxy properties configured in the @EnableAspectJAutoProxy annotation. These two properties relate to which proxy method Spring AOP will ultimately use to generate proxy objects, and whether exposed proxy objects can be obtained using aopContext.currentProxy ().

  • At this point, the functionality of the @EnableAspectJAutoProxy annotation is complete. So what are we going to do? Since this annotation adds the beanDefinition of aopProxyCreator to the Spring container, the Spring container will eventually create it, since many of Spring’s extension points require that this class bea Spring bean. So let’s take a look at what’s so special about the aopProxyCreator bean.

1.2 What is special about aopProxyCreator

  • There are instructions in chapter 1.1 aopProxyCreator this bean type is: AnnotationAwareAspectJAutoProxyCreator, that we see the relationship between the class inheritance

    Don’t see don’t know, a look startled. This bean implements the Aware and BeanPostProcessor interfaces. This is, of course, a Spring extension point, and Spring will call the corresponding methods of the two interfaces when appropriate. Here, take creating the Bean aopProxyCreator as an example to briefly describe the general meaning of each interface, namely the invocation time:

    Extension point type role trigger
    BeanFactoryAware You can get the Bean factory object in the Spring container, (You need to implement the setBeanFactory method) Triggered when the current bean is created. Eg: Currently to create the aopProxyCreator bean, will trigger
    BeanPostProcessor A top-level interface to the bean postprocessor extension point that, after the bean is created (dependency injection is complete), calls back all the postprocessor before and after methods (May need to implement postProcessBeforeInitialization and postProcessAfterInitialization method) If the aopProxyCreator bean is created, it will apply to all subsequent beans created by Spring
    InstantiationAwareBeanPostProcessor A subclass of BeanPostProcessor that extends BeanPostProcessor so that it can be used before instantiating the bean (postProcessBeforeInstantiation) and after (postProcessAfterInstantiation) do custom things. The instantiation here is simply creating the bean object,The dependency injection operation is not complete. At the same time, if in postProcessAfterInstantiation method returns false, the spring container will not do to the bean dependency injection operation. (Can realize postProcessBeforeInstantiation and postProcessAfterInstantiation method) If the aopProxyCreator bean is created, it will apply to all subsequent beans created by Spring
    SmartInstantiationAwareBeanPostProcessor A subclass of InstantiationAwareBeanPostProcessor, do to InstantiationAwareBeanPostProcessor extension. The most important methods of this post-processor are:determineCandidateConstructors, which is eventually called to determine which constructor the current bean will use to instantiate the bean (Can realize determineCandidateConstructors method) If the aopProxyCreator bean is created, it will apply to all subsequent beans created by Spring

    What is the order of execution of these postprocessors? Are you overwhelmed? Don’t lose heart, I’ve got it all ready for you. Here’s the order of execution (why know the order of execution of these post-processor? Because by knowing the execution order, you can see what role each extension point plays in aop functionality) :

    BeanFactoryAware#setBeanFactory # aopProxyCreator In aopProxyCreator this bean has been created (have been added to the spring container), and subsequent created all the beans when performing to the rear AnnotationAwareAspectJAutoProxyCreator processor is executed in the order as follows:  InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation > SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors > InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation > BeanPostProcessor#postProcessBeforeInitialization > BeanPostProcessor#postProcessAfterInitializationCopy the code

    But in fact, Only InstantiationAwareBeanPostProcessor# postProcessBeforeInstantiation and BeanPostProcessor# postProcessAfterInitialization these two Method implementation is related to AOP. So let’s focus on these two methods.

1.3 AnnotationAwareAspectJAutoProxyCreator postProcessBeforeInstantiation what have you done now

  • The source code is as follows:

    public Object postProcessBeforeInstantiation(Class
              beanClass, String beanName) throws BeansException {
        Object cacheKey = getCacheKey(beanClass, beanName);
        if(! StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {  / / @ 1
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null; }}// Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if(targetSource ! =null) {
            if (StringUtils.hasLength(beanName)) {
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        return null;
    Copy the code
  • The code at @1 is more core, and its main logic is: Decide whether the current bean is a base class (Advice. Class, Pointcut. Class, Advisor. Class, AopInfrastructureBean. Class), if not the base class, will perform shouldSkip method of logic. The shouldSkip method, on the other hand, looks for all sections in the project and the notifications defined within the sections (including sections and notifications that implement the Advisor interface, and custom sections and notifications). So how does this notification finding process work? The source code execution logic here is more complicated, so we can look at the results first:

    After this method is executed, we have the advice defined in the class found and converted into a list of Advisor types. What does Spring do? Let’s chart the shouldSkip method in detail:

    After the shouldSkip method completes, all the notifications defined in the spring container will be cached in memory. You may be wondering, how do I know which notifications apply to which pointcuts? Remember the will inform into AspectJExpressionPointcut had saved each expression from the notification? Eg: @after (value = “pointcutAnnotation()”)) So with that in mind, when I’m looking for the correspondence, let me see which tangent point has this method name, and I’ll get it, right?

    At the same time, have mentioned InstantiationModelAwarePointcutAdvisorImpl objects in the picture. It’s essentially a Advisor. In the process of looking for notification, each notice will be packaged into InstantiationModelAwarePointcutAdvisorImpl types of objects, in which the object has a particularly important attribute, is: InstantiatedAdvice, this property is of the Advice’s type. Where, for our notification type, it will be converted to the corresponding Advice. The conversion types are shown in the following table:

    The type of advice defined in the section An annotation for the notification type defined in the section Advice type
    AtBefore @Before AspectJMethodBeforeAdvice
    AtAfter @After AspectJAfterAdvice
    AtAfterReturning @AfterReturning AspectJAfterReturningAdvice
    AtAfterThrowing @AfterThrowing AspectJAfterThrowingAdvice
    AtAround @Around AspectJAroundAdvice

    The corresponding source code is as follows:

    AbstractAspectJAdvice springAdvice;
    switch (aspectJAnnotation.getAnnotationType()) {
        // Pre-notification
        case AtBefore:
            springAdvice = new AspectJMethodBeforeAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
        // Post notification
        case AtAfter:
            springAdvice = new AspectJAfterAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
        // Return a notification
        case AtAfterReturning:
            springAdvice = new AspectJAfterReturningAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
        // Exception notification
        case AtAfterThrowing:
            springAdvice = new AspectJAfterThrowingAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
        // Surround notifications
        case AtAround:
            springAdvice = new AspectJAroundAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
        // Pointcut logic
        case AtPointcut:
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            return null;
            throw new UnsupportedOperationException(
                "Unsupported advice type on method: " + candidateAdviceMethod);
    Copy the code
  • Conclusion: AnnotationAwareAspectJAutoProxyCreator postProcessBeforeInstantiation method of the main core is the container of all the aspects of the corresponding notice scan and packaged into InstantiationModelA Objects of type warePointcutAdvisorImpl are added to the cache (note here: both custom sections and sections that implement the Advisor interface will be scanned). A warm-up mechanism in which data is prepared and then retrieved directly from the cache when needed.

1.4 AnnotationAwareAspectJAutoProxyCreator postProcessAfterInitialization what have you done now

  • The source code and comments are as follows:

    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
        if(bean ! =null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey); / / @ 1}}return bean;
    Copy the code
  • The main core part of this source code is the location at @1, which is the entry point for creating the proxy object. The method names are also more familiar: wrapping if necessary, if you’re more experienced and know static proxies. The same is true here, where you generate a proxy object and wrap the target object around it. So what does the wrapIfNecessary method actually do? The source code is as follows:

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { / / @ 1
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); / / @ 2
        if(specificInterceptors ! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); / / @ 3
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    Copy the code
  • Let’s take a look at the code at @1, and see if it looks similar. Yes, it said in chapter 1.3 to AnnotationAwareAspectJAutoProxyCreator postProcessBeforeInstantiation point also appeared, is this why? Remember the order of execution of the extension points we summarized in Section 1.3? No matter a bean need be agent, will perform AnnotationAwareAspectJAutoProxyCreator post processor, and @ 1 point to the simple meaning of the code is to judge whether the current bean needs to be agent, if do not have to be agent, a bean That should be AnnotationAwareAspectJAutoProxyCreator post processor should not do any operation of bean.

  • @2 points to the code logic: to see if the bean has a defined aspect, if so, to find out the corresponding advice, eventually into a single interceptor, the subsequent generation of proxy objects, the internal maintenance of these interceptors, to achieve the purpose of invoking the defined advice.

  • @3 points to the code logic: the real logic to create the proxy object, will eventually call the following code to create the proxy object

    / / method coordinates: org. Springframework. Aop) framework. DefaultAopProxyFactory# createAopProxy
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        / / config. IsProxyTargetClass () to obtain is in the annotation @ EnableAspectJAutoProxy configuration proxyTargetClass attributes
        // If this is set to true, then go to the internal logic, otherwise go to @2 point to the code: using the JDK dynamic proxy generation
        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 is an interface, only the JDK dynamic proxy can be used
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            return new ObjenesisCglibAopProxy(config);
        else {
            return new JdkDynamicAopProxy(config);  / / @ 2}}Copy the code

    Here are some of the interview questions that can be derived:

    Q1: When aop is enabled with @enableAspectJAutoProxy annotation, do you use JDK dynamic proxy or Cglib to generate proxy objects?

    A1: The default is JDK dynamic proxy generation

    Q2: How to make Spring use Cglib to generate proxy objects? How to make Spring use JDK dynamic proxy to generate proxy objects?

    A2: Satisfy two conditions: the target class is not an interface and set proxyTargetClass to true

    Because our @enableAspectJAutoProxy annotation does not specify the use of the CGlib proxy, the resulting proxy object type is: . Org. Springframework. Aop framework. JdkDynamicAopProxy (according to the method of the return value of the signature to know).

  • Conclusion: AnnotationAwareAspectJAutoProxyCreator postProcessAfterInitialization method main role is: to create a proxy object.

1.5 Execution process of proxy objects

  • Has said in section 1.4, the final ObjectServiceImpl generated proxy object types are: org. Springframework. Aop) framework. JdkDynamicAopProxy. If you are familiar with JDK dynamic proxy, we can directly find the Invoke method in the JdkDynamicAopProxy class. The Invoke method is the entry point for our proxy object

  • The logic of the Invoke method is long, and there is a judgment on some basic methods. For example, the Object class’s equals and hashCode methods do not perform the enhancement logic, and the target method is executed directly. Therefore, all that is left is the logic that needs to be proxied. The following code shows the logic of the proxy method:

    / / method coordinates: org. Springframework. Aop) framework. JdkDynamicAopProxy# invoke
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;
        // Get the wrapper for the target object
        TargetSource targetSource = this.advised.targetSource;
        Object target = null;
        try {
            Object retVal;
            // Remember the exposeProxy property in the @enableAspectJAutoProxy annotation, which if set to true exposes the proxy object to the thread variable
            if (this.advised.exposeProxy) {
    		   We can use aopcontext.currentproxy () to get the currentProxy object
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            // Get the real target objecttarget = targetSource.getTarget(); Class<? > targetClass = (target ! =null ? target.getClass() : null);
            // This step: get the target method that is currently executing, have some notifications defined for the target method, and finally store them in the list as interceptors
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); / / @ 1
            if (chain.isEmpty()) {
                // Omit irrelevant code
            else {
                // Build the caller of the link
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); / / @ 2
                // Start to execute the method on the link
                retVal = invocation.proceed(); / / @ 3
            return retVal;
        } finally {
            if(target ! =null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
            if (setProxyContext) {
                // Restore old proxy.AopContext.setCurrentProxy(oldProxy); }}}Copy the code
  • The code specified at @1 above is basically getting a method call link, which is equivalent to building all the links if you are familiar with the chain of responsibility design pattern

  • @ 2 above the specified code in the main is to build a method invocation entry, if you are familiar with the chain of responsibility design pattern, this step is quite so will all the link set (which is called chain should be put in the first position, which will in the second position is called, which should be put in the last position is called), waiting to be triggered

  • The code specified at @3 above is the executor of the link, indicating that all methods on the link are to be executed.

  • See the following figure for the appearance and execution process of this link:

    In the previous article, Spring AOP Usage: Familiar with the use of pre-notification, post-notification, return notification, exception notification, and understanding the features of the various kinds of notifications described in the previous article, Spring AOP Usage: Familiar with the use of pre-notification, Post-notification, return notification, and exception notification. First, the method call stack starts with the exception notification, which has a large try catch block that catches the exception thrown by the link and then executes the exception notification. Second, the postnotice is on the second link and is bound to be executed because there is a try finally block inside and the postnotice is executed in the finally block. Second, the return notification is on the third link. There is no try finally block in the return notification, so the return notification may not be executed. Finally, the pre-notification is on the fourth link, which is synchronized with the execution of the target method. According to the above analysis, only the pre-notification is triggered before the execution of the target method, and the rest of the post-notification, return notification, and exception notification should be executed according to the code logic after the execution of the target method.

Second, the summary

  • Spring AOP principle, from the source code level, from the @enableAspectJAutoProxy annotation began, to generate proxy object and proxy object execution order are summarized again, hope to help you!

  • Feel free to like, bookmark and follow my posts if you find them useful. :laughing:

  • I’m a slow walker, but I never walk backwards