Springboot extension point series_ApplicationContextAwareProcessor

Features

ApplicationContextAwareProcessor itself is not an extension point, but implements BeanPostProcessor and implements postProcessBeforeInitialization(), so there is no need to implement it, but it contains the execution timing of the following 6 interfaces. The functions of these interfaces are: :

1. EnvironmentAware: Used to obtain Environment. Environment can obtain all parameters in the system. In addition, Environment can also be obtained through injection. Which method is used depends on the implementation scenario.

2. EmbeddedValueResolverAware: used to obtain StringValueResolver. StringValueResolver can obtain variables based on properties of the String type; in addition, you can also use the @Value method to obtain variables of properties. Which method is used depends on the implementation scenario.

3. ResourceLoaderAware: used to obtain ResourceLoader. ResourceLoader can be used to obtain all resource objects in the classpath.

4. ApplicationEventPublisherAware: used to obtain ApplicationEventPublisher. ApplicationEventPublisher can be used to publish events. Of course, this object can also be obtained through spring injection. For specific implementation methods, please refer to the actual application of Springboot event listening mechanism.

5. MessageSourceAware: used to obtain MessageSource. MessageSource is mainly used for internationalization.

6. ApplicationContextAware: Used to obtain ApplicationContext, which is the Spring context manager.

The following defines a Bird class to implement the ApplicationContextAware interface, and uses Bird as an example to share the functional features of ApplicationContextAwareProcessor.

@Component
@Slf4j
public class Bird implements ApplicationContextAware {<!-- -->
    private String name="xiao niao";
    private ApplicationContext applicationContext;
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {<!-- -->
        this.applicationContext=applicationContext;
        log.info("----Spring context application is injected");
    }
}

@Test
    public void test3(){<!-- -->
        log.info("----Unit test execution starts");
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.fanfu");
        log.info("----Unit test execution completed");
 
    }

Unit test execution results

img

How it works

Registration Timing

The registration timing of ApplicationContextAwareProcessor is when preparing BeanFactory. The registration entry is in the AbstractApplicationContext#refresh—–>AbstractApplicationContext#prepareBeanFactory method.

img

Execution logic

The extension logic of ApplicationContextAwareProcessor#postProcessBeforeInitialization is very simple: that is, whether the current Bean implements EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, and ApplicationContextAware. If not, it will be returned directly. If it is, the extension logic of the XxxAware interface will be executed;

class ApplicationContextAwareProcessor implements BeanPostProcessor {<!-- -->
   private final ConfigurableApplicationContext applicationContext;
   private final StringValueResolver embeddedValueResolver;
   
   public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {<!-- -->
      this.applicationContext = applicationContext;
      this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
   }
   @Override
   @Nullable
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {<!-- -->
       //If not implementing EnvironmentAware, EmbeddedValueResolverAware,
       //ResourceLoaderAware, ApplicationEventPublisherAware,
       //MessageSourceAware, ApplicationContextAware, then pull directly and return;
      if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
            bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
            bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){<!-- -->
         return bean;
      }
      AccessControlContext acc = null;
      if (System.getSecurityManager() != null) {<!-- -->
         acc = this.applicationContext.getBeanFactory().getAccessControlContext();
      }
      if (acc != null) {<!-- -->
         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {<!-- -->
            invokeAwareInterfaces(bean);
            return null;
         }, acc);
      }
      else {<!-- -->
          //If the XXXAware interface is implemented, execute the extension method of the relevant Aware interface;
         invokeAwareInterfaces(bean);
      }
      return bean;
   }
   private void invokeAwareInterfaces(Object bean) {<!-- -->
      if (bean instanceof EnvironmentAware) {<!-- -->
         ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
      }
      if (bean instanceof EmbeddedValueResolverAware) {<!-- -->
         ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
      }
      if (bean instanceof ResourceLoaderAware) {<!-- -->
         ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
      }
      if (bean instanceof ApplicationEventPublisherAware) {<!-- -->
         ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
      }
      if (bean instanceof MessageSourceAware) {<!-- -->
         ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
      }
      if (bean instanceof ApplicationContextAware) {<!-- -->
         ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
      }
   }
}

Execution Timing

Because ApplicationContextAwareProcessor implements the BeanPostProcessor interface and rewrites postProcessBeforeInitialization(). Regarding the execution timing of the BeanPostProcessor interface, you can move to the BeanPostProcessor of the Springboot extension point, and I will not repeat it here.

img

Summary

Through the above analysis, we can understand:

1. ApplicationContextAwareProcessor implements the BeanPostProcessor interface, which is the internal classic implementation of the Spring extension point BeanPostProcessor.

2. The internal logic of ApplicationContextAwareProcessor#postProcessBeforeInitialization is very simple. It mainly implements the specific implementation of XxxAware related extension interfaces;

3. ApplicationContextAwareProcessor is registered relatively early, that is, after BeanFactory is instantiated and related properties are initialized;

4. The execution timing of ApplicationContextAwareProcessor#postProcessBeforeInitialization is after the Spring-managed Bean instantiation and property injection are completed, but before the InitializingBean#afterPropertiesSet method and the custom initialization method;