Spring源码解析系列三:Spring的后置处理器到底是怎么回事?

这里要介绍的是Spring的扩展类点之一的:BeanPostProcessor. 废话不多说,开搞!

1.准备代码

在这里插入图片描述

  • TestProcessor类
@Component
public class TestProcessor implements BeanPostProcessor ,PriorityOrdered{
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (beanName.equals("personService")){
			System.out.println("BeforeInitialization1");
		}
		return bean;
	}
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (beanName.equals("personService")){
			System.out.println("AfterInitialization1");
		}
		return bean;
	}
	@Override
	public int getOrder() {
		return 200;
	}
}
  • TestProcessor2类
@Component
public class TestProcessor2 implements BeanPostProcessor,PriorityOrdered {
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      if (beanName.equals("personService")){
         System.out.println("BeforeInitialization2");
      }
      return bean;
   }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      if (beanName.equals("personService")){
         System.out.println("AfterInitialization2");
      }
      return bean;
   }
   @Override
   public int getOrder() {
      return 199;
   }
}
  • PersonService类
@Component
public class PersonService {
   public PersonService() {
      System.out.println("personService构造方法执行了");
   }
   @PostConstruct
   public void init(){
      System.out.println("init方法执行了");
   }
}
  • PersonService2类
@Component
public class PersonService2 implements ApplicationContextAware {
   private ApplicationContext applicationContext;
   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
      System.out.println("全局对象:"+ applicationContext);
   }
}
  • SpringConfiguration类
@ComponentScan("com.v1")
public class SpringConfiguration {

}
  • Test01类
public class Test01 {
   public static void main(String[] args) {
      //这个构造方法会把Spring所有的环境都准备好
      AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
   }
}

2.点击 AnnotationConfigApplicationContext

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
   //这个类有父类,所以会先初始化父类的构造方法,接着初始化自己的构造方法
   //调用无参构造方法进行初始化一个读取器和扫描仪
   this();
   //把配置类加载进 DefaultListableBeanFactory 的map集合中
   //配置类可以一次性传多个,这个方法执行后,只是把配置类加载进了 DefaultListAbleBeanFactory的map集合中
   //还没有扫描其他的的加了组件的类
   register(annotatedClasses);
   //实例化所有被加了组件的对象
   refresh();
}

3.点击 refresh() 方法

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
      //这个方法不是重点,可以暂时认为他不干任何事情
      prepareRefresh();

      //获取工厂对象 ,本质是DefaultListableBeanFactory对象
      //其实读取xml文件变成beanDefinition,也是在这里面完成的
      //所以这里面的功能和register(annotatedClasses);功能很像
      //一个是是从xml文件中读取配置信息,一个是通过类的注解读取信息
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      //为BeanFactory配置类加载器、后置处理器等等
      //这个方法比较重要
      prepareBeanFactory(beanFactory);
       
       //剩余的代码省略.....
   }

4.点击 prepareBeanFactory 方法

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {

   //添加一个类加载器
   beanFactory.setBeanClassLoader(getClassLoader());

   //bean的表达式解析,以后再讲,在前台页面可以获取到bean表达式的一些属性
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

   //对象与string类型的转换  <property >
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));


   //重要方法
   //为Spring添加后置处理器 ApplicationContextAwareProcessor 实现了BeanProcessor接口
   //我们主要查看 重写接口的 postProcessBeforeInitialization ()方法
   //主要作用:判断当前bean对象实现了里面的那些接口,从而在bean类获取对应的对象
   //一般我们会实现 ApplicationContextAware 接口获取 applicationContext
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

   //以下是添加自动注入忽略的列表,不是重点
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   //等讲到bean的实例化的过程时,会说明
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

 //这个ApplicationListenerDetector作用: 某个类实现了ApplicationListener接口,可以获取到一个ApplicationEvent对象
   //ApplicationEvent对象存储有reader,scanner,registry,beanFactory等对象
   //注意实现ApplicationListener的前提是,这个bean必须是单例的
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    //剩余的代码省略.....
}

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

解析这个方法之前,我们看一下 BeanFactory工厂里面到底存放了哪些数据

在这里插入图片描述

粉色部分就是 BeanFactory 的示意图

  • 绿色部分: Spring初始化的时候,所有的beanDefinition都存储在这个beanDefinitionMap集合中
  • 黄色部分:beanDefinitionNames集合存储所有 beanDefinition的名称
  • 深紫部分: beanPostProcessors集合存储着所有的后置处理器,也就是实现了 BeanPostProcessor接口的类
  • 浅绿部分: getBeanNamesForType, beanFactory中的一个方法,通过类型得到一个beanName
  • 浅紫部分: singletonObjects,实例化后的类会存储在这个集合中

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))

这个方法把 ApplicationContextAwareProcessor 添加进了 beanPostProcessors,说明这个类是一个实现了

BeanPostProcessors的后置处理器

5.点击 ApplicationContextAwareProcessor `

查看 ApplicationContextAwareProcessor,果然它实现了 BeanPostProcessor

6.点击 BeanPostProcessor


public interface BeanPostProcessor {
     
   /* 
    * 在bean的初始化之前执行
    */
   @Nullable
   default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      return bean;
   }
   
   /*
    * 在bean的初始化之后执行
    */
   @Nullable
   default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      return bean;
   }

}
  • BeanPostProcessor是Spring框架提供的一个扩展类点之一
  • 扩展类点其实有很多种的 例如实现 BeanFactoryPostProcessor接口也是
  • BeanPostProcessor作用:
    • 通过实现BeanPostProcessor接口,程序员就可以插手bean的实例化过程,从而减轻beanFactory的负担
    • 这个接口可以被多个类实现,会形成一个列表, 通过实现PriorityOrdered可以改变实现类的执行顺序,getOrder返回值越小越优先执行
    • AOP的就是在bean实例化后期将切面逻辑织入bean实例中的
    • AOP也是通过BeanPostProcessor和IOC容器建立起了联系

Spring默认提供很多BeanPostProcessor的实现类
其实这个接口的本身方法特别的简单,简单到令人发指,但是他的实现类巨多,实现类的方法内的逻辑复杂的程 度也令人发指

前面我们准备了两个处理器 TestProcessor,TestProcessor2都实现了 BeanPostProcessorPriorityOrdered

  • TestProcessor类
@Component
public class TestProcessor implements BeanPostProcessor ,PriorityOrdered{
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //所有的类的实例化过程中都会执行执行实现了BeanPostProcessor后置处理器
        //为了避免其他类做实例化的时候,也打印BeforeInitialization1,影响测试
		if (beanName.equals("personService")){
			System.out.println("BeforeInitialization1");
		}
		return bean;
	}
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (beanName.equals("personService")){
			System.out.println("AfterInitialization1");
		}
		return bean;
	}
	@Override
	public int getOrder() {
		return 200;
	}
}
  • TestProcessor2类
@Component
public class TestProcessor2 implements BeanPostProcessor,PriorityOrdered {
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      if (beanName.equals("personService")){
         System.out.println("BeforeInitialization2");
      }
      return bean;
   }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      if (beanName.equals("personService")){
         System.out.println("AfterInitialization2");
      }
      return bean;
   }
   @Override
   public int getOrder() {
      return 199;
   }
}

两个后置处理器都实现了 BeanPostProcessor的init和after方法,实现了 PriorityOrderedgetOrder方法

实现 getOrder的后置处理器,返回值为 int 类型,返回值越小,执行的顺序越靠前

我们回到 Test01运行测试类

测试结果:

personService构造方法执行了
BeforeInitialization2
BeforeInitialization1
init方法执行了
AfterInitialization2
AfterInitialization1
全局对象:org.springframework.context.annotation.AnnotationConfigApplicationContext@100955a, started on Sun Dec 08 11:48:03 CST 2019

7.我们回到 ApplicationContextAwareProcessor类中

既然我们已经知道了 BeanPostProcessors的作用,我们看看 ApplicationContextAwareProcessor这个Spring内部的后置处理器的init方法和after方法里面到底干了哪些事

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(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;
       //这个方法不会进入
		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			//这个重点
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	/**
	 * 判断当前的bean,实现了什么类型的接口,然后根据判断设置类
	 * @param bean
	 */
	private void invokeAwareInterfaces(Object bean) {
        
		if (bean instanceof Aware) {
	//(1)如果bean实现了EnvironmentAware接口,可以获取环境对象
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
            
	//(2)如果bean实现了EmbeddedValueResolverAware接口,可以获取embeddedValueResolver对象
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
            
	//(3)如果bean实现了ResourceLoaderAware接口,可以获取applicationContext工厂对象
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
            
 //(4)如果bean实现了ApplicationEventPublisherAware接口,可以获取applicationContext工厂对象
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
            
 //(5)如果bean实现了MessageSourceAware接口,可以获取applicationContext工厂对象
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
            
//(6)如果该bean实现了ApplicationContextAware接口 ,那么就把工厂applicationContext,传进去
//在bean的类中重写ApplicationContextAware的set方法 就可以在该bean中获取到整个工厂
//这时候想获取哪个对象都可以了
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}

}

通过查看 ApplicationContextAwareProcessor处理器,我们发现 ,它同样是实现了 BeanPostFactory的两个方法 postProcessBeforeInitializationpostProcessAfterInitialization方法,但是 后置方法并没有干任何事,我们重点查看 前置方法

ApplicationContextAwareProcessor方法中,调用 invokeAwareInterfaces方法,

查看 invokeAwareInterfaces方法,我们查询,只要实现某一个接口就能获取相应的对象

例如在准备代码中,我们的 PersonService2实现了 ApplicationContextAware接口

@Component
public class PersonService2 implements ApplicationContextAware {
   private ApplicationContext applicationContext;
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
		System.out.println("全局对象:"+ applicationContext);
	}
}

实现了 setApplicationContext就可以获取全局对象

假设你这样一个需求,需要初始化的时候获取到Spring的全局对象,那么你就可以实现 ApplicationContextAware

总结一下 ApplicationContextAwareProcessor到底干了哪些事?

  1. 实现了 BeanPostProcessors接口
  2. postProcessBeforeInitialization方法里面执行 invokeAwareInterfaces方法
  3. invokeAwareInterfaces方法中,判断当前的Bean实现了哪些接口,如果实现了某个接口就可以获取对应的对象

8.我们回到 第四步 点击 prepareBeanFactory `方法

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {

   //添加一个类加载器
   beanFactory.setBeanClassLoader(getClassLoader());

   //bean的表达式解析,以后再讲,在前台页面可以获取到bean表达式的一些属性
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

   //对象与string类型的转换  <property >
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));


   //重要方法
   //为Spring添加后置处理器 ApplicationContextAwareProcessor 实现了BeanProcessor接口
   //我们主要查看 重写接口的 postProcessBeforeInitialization ()方法
   //主要作用:判断当前bean对象实现了里面的那些接口,从而在bean类获取对应的对象
   //一般我们会实现 ApplicationContextAware 接口获取 applicationContext
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

   //以下是添加自动注入忽略的列表,不是重点
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   //等讲到bean的实例化的过程时,会说明
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

 //这个ApplicationListenerDetector作用: 某个类实现了ApplicationListener接口,可以获取到一个ApplicationEvent对象
   //ApplicationEvent对象存储有reader,scanner,registry,beanFactory等对象
   //注意实现ApplicationListener的前提是,这个bean必须是单例的
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    //剩余的代码省略.....
}

在该方法中 ,不仅添加了 ApplicationContextAwareProcessor,这个后置处理器,其实还添加了 ApplicationListenerDetector这个处理器

9.点击 ApplicationListenerDetector

我们主要查看 postProcessAfterInitialization方法

@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		//判断当前的bean是否实现了ApplicationListener这个接口,如果没有实现直接跳过
		if (bean instanceof ApplicationListener) {
			//如果有实现,则判断当前的bean实现是单例的
			//singletonNames存储用户所有的bean,
			// key值为 beanName ,value值为Boolean值 false 代表为不是单例  true代表为单例
			Boolean flag = this.singletonNames.get(beanName);
			if (Boolean.TRUE.equals(flag)) {

				this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
			}
			else if (Boolean.FALSE.equals(flag)) {
				if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
					// inner bean with other scope - can't reliably process events
					logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
							"but is not reachable for event multicasting by its containing ApplicationContext " +
							"because it does not have singleton scope. Only top-level listener beans are allowed " +
							"to be of non-singleton scope.");
				}
				//如果不是单例的,删除掉
				this.singletonNames.remove(beanName);
			}
		}
		return bean;
	}

这个方法主要作用:

执行了 ApplicationListener,必须是 单例的,才可以获取到相应的对象

视频讲解:

<https://www.bilibili.com/video/av67899876?p=4>

视频为自己学习的时候录制的,也方便自己以后看

Spring5源码地址:

<https://gitee.com/zouchangfu/spring_5_source_code>

Spring5源码都是已经构建好的了,无需再使用gradle进行构建了,直接打开就可以跑起来

写在最后:

大二学生一枚,挤时间写博客不容易,看完顺手点个赞,你的点赞是对我最大的鼓励

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值