Spring - ApplicationContextAwareProcessor扩展接口

Posted 小小工匠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring - ApplicationContextAwareProcessor扩展接口相关的知识,希望对你有一定的参考价值。

文章目录


Pre

Spring Boot - 扩展接口一览


org.springframework.context.support.ApplicationContextAwareProcessor

/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.support;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationStartupAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.lang.Nullable;
import org.springframework.util.StringValueResolver;

/**
 * @link BeanPostProcessor implementation that supplies the @code ApplicationContext,
 * @link org.springframework.core.env.Environment Environment, or
 * @link StringValueResolver for the @code ApplicationContext to beans that
 * implement the @link EnvironmentAware, @link EmbeddedValueResolverAware,
 * @link ResourceLoaderAware, @link ApplicationEventPublisherAware,
 * @link MessageSourceAware, and/or @link ApplicationContextAware interfaces.
 *
 * <p>Implemented interfaces are satisfied in the order in which they are
 * mentioned above.
 *
 * <p>Application contexts will automatically register this with their
 * underlying bean factory. Applications do not use this directly.
 *
 * @author Juergen Hoeller
 * @author Costin Leau
 * @author Chris Beams
 * @since 10.10.2003
 * @see org.springframework.context.EnvironmentAware
 * @see org.springframework.context.EmbeddedValueResolverAware
 * @see org.springframework.context.ResourceLoaderAware
 * @see org.springframework.context.ApplicationEventPublisherAware
 * @see org.springframework.context.MessageSourceAware
 * @see org.springframework.context.ApplicationContextAware
 * @see org.springframework.context.support.AbstractApplicationContext#refresh()
 */
class ApplicationContextAwareProcessor implements BeanPostProcessor 

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	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 (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
				bean instanceof ApplicationStartupAware)) 
			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 
			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 ApplicationStartupAware) 
			((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
		
		if (bean instanceof ApplicationContextAware) 
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		
	



ApplicationContextAwareProcessor 本身并没有扩展点,但是该类内部却有6个扩展点可供实现 ,这些类触发的时机在bean实例化之后,初始化之前.


内部的7个扩展点

5.3.2版本

	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 ApplicationStartupAware) 
			((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
		
		if (bean instanceof ApplicationContextAware) 
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		
	
  • EnvironmentAware:用于获取EnviromentAware的一个扩展类,这个变量非常有用, 可以获得系统内的所有参数。个人认为这个Aware没必要去扩展,因为spring内部都可以通过注入的方式来直接获得。

  • EmbeddedValueResolverAware:用于获取StringValueResolver的一个扩展类, StringValueResolver用于获取基于String类型的properties的变量,一般都用@Value的方式去获取,如果实现了这个Aware接口,把StringValueResolver缓存起来,通过这个类去获取String类型的变量,效果是一样的。

  • ResourceLoaderAware:用于获取ResourceLoader的一个扩展类,ResourceLoader可以用于获取classpath内所有的资源对象,可以扩展此类来拿到ResourceLoader对象。

  • ApplicationEventPublisherAware:用于获取ApplicationEventPublisher的一个扩展类,ApplicationEventPublisher可以用来发布事件,结合ApplicationListener来共同使用。这个对象也可以通过spring注入的方式来获得。

  • MessageSourceAware:用于获取MessageSource的一个扩展类,MessageSource主要用来做国际化。

  • ApplicationStartupAware: 要开始收集定制的StartupStep,组件可以实现ApplicationStartupAware接口直接获得ApplicationStartup实例或者在注入点请求ApplicationStartup类型。

  • ApplicationContextAware:用来获取ApplicationContext的一个扩展类, ApplicationContext应该是很多人非常熟悉的一个类了,就是spring上下文管理器,可以手动的获取任何在spring上下文注册的bean,我们经常扩展这个接口来缓存spring上下文,包装成静态方法。同时ApplicationContext也实现了BeanFactory,MessageSource,ApplicationEventPublisher等接口,也可以用来做相关接口的事情。


源码解析

org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization

我们继续看下 invokeAwareInterfaces(bean);

可知ApplicationContextAwareProcessor关联了大部分Spring内置Aware接口,它们的执行顺序如下:

EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware -> ApplicationEventPublisherAware -> MessageSourceAware -> ApplicationStartupAware -> ApplicationContextAware

我们来看下调用栈

org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
	BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		org.springframework.beans.factory.support.AbstractBeanFactory#getBean
		  org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean	
			  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
					org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
						 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
								applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
										processor.postProcessBeforeInitialization(result, beanName);
											org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
													org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces

扩展示例

 package com.artisan.bootspringextend.testextends;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.*;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.weaving.LoadTimeWeaverAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;

/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2022/12/4 11:02
 * @mark: show me the code , change the world
 */
@Slf4j
@Component
public class ExtendInvokeAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware,
        ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,ApplicationStartupAware, ApplicationContextAware, ImportAware,
        LoadTimeWeaverAware 

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) 
        log.info(" ------> BeanClassLoaderAware::setBeanClassLoader invoked");
    

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException 
        log.info(" ------> BeanFactoryAware::setBeanFactory invoked");
    

    @Override
    public void setBeanName(String s) 
        log.info(" ------> BeanNameAware::setBeanName invoked");
    

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
        log.info(" ------> ApplicationContextAware::setApplicationContext invoked");
    

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) 
        log.info(" ------> ApplicationEventPublisherAware::setApplicationEventPublisher invoked");
    

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) 
        log.info(" ------> EmbeddedValueResolverAware::setEmbeddedValueResolver invoked");
    

    @Override
    public void setEnvironment(Environment environment) 
        log.info(" ------> EnvironmentAware::setEnvironment invoked");
    

    @Override
    public void setMessageSource(MessageSource messageSource) 
        log.info(" ------> MessageSourceAware::setMessageSource invoked");
    

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) 
        log.info(" ------> ResourceLoaderAware::setResourceLoader invoked");
    

    @Override
    public void setApplicationStartup(ApplicationStartup applicationStartup) 
        log.info(" ------> ApplicationStartup::setApplicationStartup invoked");
    

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) 
        log.info(" ------> ImportAware::setImportMetadata invoked");
    

    @Override
    public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) 
        log.info(" ------> LoadTimeWeaverAware::setLoadTimeWeaver invoked");
    




输出结果

  .   ____          _            __ _ _
 /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\
( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\
 \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.2)

2022-12-04 19:14:25.103  INFO 12832 --- [           main] .b.t.ExtendApplicationContextInitializer : ExtendApplicationContextInitializer # initialize  Called
2022-12-04 19:14:25.110  INFO 12832 --- [           main] c.a.b.BootSpringExtendApplication        : Starting BootSpringExtendApplication using Java 1.8.0_261 on LAPTOP-JF3RBRRJ with PID 12832 (D:\\IdeaProjects\\boot2\\boot-spring-extend\\target\\classes started by artisan in D:\\IdeaProjects\\boot2)
2022-12-04 19:14:25.111  INFO 12832 --- [           main] c.a.b.BootSpringExtendApplication        : No active profile set, falling back to default profiles: default
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ------> BeanNameAware::setBeanName invoked
2022-12-04 19:14:25.444  INFO 12832 --- [           main] c.a.b.testextends.ExtendInvokeAware      :  ----以上是关于Spring - ApplicationContextAwareProcessor扩展接口的主要内容,如果未能解决你的问题,请参考以下文章

Spring + Hibernate + JPA [关闭]

Spring Web 项目Junit测试报错问题

Spring 类构造器初始化实例

ContextLoader和ContextLoaderListener

ContextLoader和ContextLoaderListener

面试阿里,字节,美团必看的Spring的Bean管理详解