Spring源码衍生篇一:BeanPostProcessor

目录

1. BeanPostProcessor思维导图

2.InstantiationAwareBeanPostProcessor

2.1postProcessBeforeInstantiation

2.2postProcessAfterInstantiation

2.3postProcessProperties

3.SmartInstantiationAwareBeanPostProcessor

3.1determineCandidateConstructors()

3.2getEarlyBeanReference()

4.MergedBeanDefinitionPostProcessor

5.DestructionAwareBeanPostProcessor

6、原生实现类

7、注册时机


最近在写spring bean的生命周期的时候,发现无论如何都绕不开BeanPostProcessor后置处理器,这货有多强呢?bean的生命周期和九大处理器可有所耳闻?先简短描述一下bean生命周期,其实就是bean的实例化、属性赋值、初始化、销毁四大阶段,而这四大阶段里又穿插着九大后置处理器,如果单独记忆这九大后置处理器,那真的是<<JAVA从入门到放弃>>,可是归纳起来看,你就会发现这些处理器都是来自于同一个爸爸--BeanPostProcessor接口,而最重要的几个子接口分别是:

1、InstantiationAwareBeanPostProcessor

2、SmartInstantiationAwareBeanPostProcessor

3、MergedBeanDefinitionPostProcessor

4、DestructionAwareBeanPostProcessor

他有两个原生方法,分别在bean的初始化前后调用,方法如下

postProcessBeforeInitialization(Object bean, String beanName)

postProcessAfterInitialization(Object bean, String beanName)

下面开讲之前先给大家看一下文章结构

1.展示beanPostProcessor思维导图

2.分别讲解几个子类接口/子实现类的作用

3.注册时机

1. BeanPostProcessor思维导图

先上流程图

看不清可以来下面链接看

Spring生命周期思维导图| ProcessOn免费在线作图,在线流程图,在线思维导图

继承图如下:(至关重要!!!)

在图里可以发现,有两个子类继承了他的祖辈们的财产,分别是AutowiredAnnotationBeanPostProcessorCommonAnnotationPostProcessos ,下面讲的那几个接口,很多时候都是靠他们两个实现类去实现的。

2.InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor有三个方法,而默认实现类是AbstractAutoProxyCreator

1. postProcessBeforeInstantiation() 在bean实例化前调用,也是第一次扩展后置处理器的调用时机。

2.postProcessAfterInstantiation()在bean实例化后、属性赋值前 调用,第五次扩展后置处理器的调用时机。

3. postProcessPropertyValues() @Autowired在这里进行DI,将获取的属性封装在 PropertyValues 的实例对象 pvs 中,在属性赋值阶段,第六次扩展后置处理器的调用时机

先直接上一段代码:

建一个Son类和Father类,son类继承father类

public class Father {



	private int id;

	private String name;

	private int age;

	public int getId() {
		return id;
	}

	public void setId( int id ) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName( String name ) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge( int age ) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Father{" +
				"id=" + id +
				", name='" + name + '\'' +
				", age=" + age +
				'}';
	}
}
public class Son extends Father{

   private String money;

   public String getMoney() {
      return money;
   }

   public void setMoney( String money ) {
      this.money = money;
   }

   @Override
   public String toString() {
      return "Son{" +
            "money='" + money + '\'' +
            '}';
   }
}
spring.xml


/**
 * @Author 小源仔
 * @Date 2023/5/9 21:10
 * @description:
 */
public class BeanInstantiationDemo {

	public static void main( String[] args ) {
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		beanFactory.addBeanPostProcessor( new MyInstantiationAwareBeanPostProcessor() );
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		String location = "spring.xml";
		Resource resource = new ClassPathResource(location);
		//字符编码格式
		EncodedResource encodedResource = new EncodedResource(resource,"UTF-8");
		beanDefinitionReader.loadBeanDefinitions( encodedResource );
		Son son = beanFactory.getBean("son",Son.class);
		System.out.println(son);
//		Father father = beanFactory.getBean( "father",Father.class );
//		System.out.println(father);

	}

	static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
		/**
		 * 实例化bean之前,相当于new这个bean之前
		 * 当调用postProcessBeforeInstantiation返回对象时,就可以直接返回对象了,就不会走到AbstractAutowireCapableBeanFactory的doCreateBean方法
		 */
		@Override
		public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
			System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation,beanName="+beanName);
			return null;
		}

		/**
		 * 实例化bean之后,相当于new这个bean之后
		 * 如果返回值是false,那么就不进行下面的依赖注入流程了
		 */
		@Override
		public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
			System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation");
			return true;
		}

		/**
		 * bean已经实例化完成,在属性注入时阶段触发,
		 * Instantiation(实例化)
		 */
		@Override
		public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
			System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessProperties");
			return null;
		}

		//    /**
		//     * 这个方法在spring低版本中使用,在高版本已经过时了,使用postProcessProperties代替
		//     * deprecated as of 5.1, in favor of {@link #postProcessProperties(PropertyValues, Object, String)}
		//     * @param pvs
		//     * @param pds
		//     * @param bean
		//     * @param beanName
		//     * @return
		//     * @throws BeansException
		//     */
		//    @Override
		//    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
		//        return null;
		//    }

		/**
		 * 初始化bean之前,相当于把bean注入spring上下文之前
		 * Initialization(初始化)
		 */
		@Override
		public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
			System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization");
			return bean;
		}

		/**
		 * 初始化bean之后,相当于把bean注入spring上下文之后
		 */
		@Override
		public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
			System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization");
			return bean;
		}
	}

}

这个代码里面把所有方法都给实现了一遍,具体顺序自己看图里。

2.1postProcessBeforeInstantiation

这个方法因为是在对象实例化前调用,如果返回的是具体的对象,而不是null的话,这个返回值就会代替原来该生成的目标对象的实例,相当于偷梁换日了。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走

举例子:

还是上面代码,稍微改一下:

public static void main( String[] args ) {
      DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
      beanFactory.addBeanPostProcessor( new MyInstantiationAwareBeanPostProcessorV2() );
      XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
      String location = "spring.xml";
      Resource resource = new ClassPathResource(location);
      //字符编码格式
      EncodedResource encodedResource = new EncodedResource(resource,"UTF-8");
      beanDefinitionReader.loadBeanDefinitions( encodedResource );
      Son son = beanFactory.getBean("son",Son.class);
      System.out.println(son);
//    Father father = beanFactory.getBean( "father",Father.class );
//    System.out.println(father);

   }


static class MyInstantiationAwareBeanPostProcessorV2 implements InstantiationAwareBeanPostProcessor{
   @Override
   public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
      if(ObjectUtils.nullSafeEquals("son",beanName) && Son.class.equals(beanClass)){
         //把配置完成的 superUser bean覆盖
         return  new Father();
      }
      return null;//这里表示什么都不变化
   }
}

debug进源码跟大家看一下:

因为流程比较多,所以我用文字来表达一下前面的流程:

1.org.springframework.beans.factory.support.AbstractBeanFactory#getBean(String name, Class<T> requiredType)

2.AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

3.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)

执行完核心方法后,正常返回的bean是null,可是因为我们前面让bean有返回值了,所以下面源码在继续debug的时候就能看到它返回一个father对象,替换了原先的son对象,成功“偷梁换日”

继续进入applyBeanPostProcessorsBeforeInstantiation()方法,这里就是循环实现了InstantiationAwareBeanPostProcessor的接口,其实就只有一个接口,那就是我们自定义的

然后继续进入postProcessBeforeInstantiation方法里

返回到上两步

因为bean生成了代理对象,所以会继续调用applyBeanPostProcessorsAfterInitialization,如果有实现了postProcessAfterInstantiation()这个方法,就会被直接执行。如果没有生成代理对象,这个方法将会在后面实例化对象后,则第五次扩展后置处理器,还会被调用到。

2.2postProcessAfterInstantiation

上面流程已经讲述了这个方法的作用,这里就不再多讲

2.3postProcessProperties

还记得我们最前面自定义的代码吗,现在默认beanPostProcessorsBeforeInitialization()方法返回是空值(否则走不到postProcessProperties这一步),然后重新执行一遍代码,我带大家看看他的调用流程

1.org.springframework.beans.factory.support.AbstractBeanFactory#getBean(String name, Class<T> requiredType)

2.AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

3.AbstractAutowireCapableBeanFactory#doCreateBean(beanName, mbdToUse, args)

进入populateBean()方法,从这里可以看出是在属性赋值阶段执行这个后置处理器的

AutowiredAnnotationBeanPostProcessor 中的 postProcessProperties 方法

记住这里,下面会讲到!!!会首尾呼应!!!

postProcessProperties 方法就是把缓存中已经被解析的@Autowired、@value、@Resource的属性、方法拿出来,属性赋值进bean实例中

3.SmartInstantiationAwareBeanPostProcessor

有意思啊,这个smartInstantiationAwareBeanPostProcessor接口,居然是前面讲的InstantiationAwareBeanPostProcessor的儿子。不禁感慨真就上阵父子兵啊!

我们来看下他的两个方法:

1.determineCandidateConstructors() 选举出合适的构造函数对象(如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来)

2.getEarlyBeanReference() 解决循环依赖,提前暴露一个工厂,工厂是三级缓存

3.1determineCandidateConstructors()

继续上面的代码debug:

1.org.springframework.beans.factory.support.AbstractBeanFactory#getBean(String name, Class<T> requiredType)

2.AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

3.AbstractAutowireCapableBeanFactory#doCreateBean(beanName, mbdToUse, args)

createBeanInstance()核心逻辑是寻找合适的构造器,并实例化对象,下面进入createBeanInstance()方法

继续进入

一般我们不需要自定义接口去寻找他的构造器,他有实现类AutowiredAnnotationBeanPostProcessor,@AutoWired注解在构造器上时才会触发这个后置处理器的使用,这里就不继续讲他的实现类了。

3.2getEarlyBeanReference()

这个方法可有意思,spring大名鼎鼎的依赖注入就是在这里实现第一步的,他提前曝光了一个工厂对象,是一个三级缓存来的(singletonFactories),用于创建beanName所对应的Bean对象。这个bean是前面实例化后,还未到属性赋值阶段的

简单说一下spring三级缓存:

Map<String, Object> singletonObjects (一级缓存)

key:beanName,value:经历了spring完整生命周期的bean对象。

Map<String, Object> earlySingletonObjects(二级缓存)

key:beanName,value:不完整的单例对象,也就是还没有初始化完毕。

Map<String, ObjectFactory<?>> singletonFactories(三级缓存)

key:beanName,value:单例工厂,用于创建beanName所对应的Bean对象。

在AbstractAutowireCapableBeanFactory的doCreateBean()方法中,在对bean实例化以后填充属性之前(一般称为早期对象,还没被属性赋值),会将其放入第三级缓存

addSingletonFactory:把我们的早期对象包装成一个singletonFactory,该对象提供了一个getObject方法,该方法内部调用的就是getEarlyBeanReference()方法

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

看下addSingletonFactory(),他就是把工厂对象给存了起来

进入getEarlyBeanReference()方法中:

AbstractAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor的实现类之一,其重写了getEarlyBeanReference方法:

一看就是跟动态代理相关的

4.MergedBeanDefinitionPostProcessor

这个后置处理器只有CommonAnntationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor两个实现类是有内容的,其他的都是空实现。他们两个的功能很类似,就是把实例化后的bean对象,解析它里面的@Resource 、@Autowired、@Value属性和方法,封装成InjectionMetadata类型,并放进缓存中,等属性赋值阶段时再从缓存中拿出数据来赋值

我们看一下AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors()方法

进入AutowiredAnnotationBeanPostProcessor的方法

CommonAnntationBeanPostProcessor也类似是这样,只不过是获取@Resource注解的属性/方法而已,这里就不赘述了。

还记得前面说的吗?封装成InjectionMetadata类型,并放进缓存中,等属性赋值阶段时再从缓存中拿出数据来赋值 我们也来看一下是怎么样获取到缓存数据的吧,我知道看到这里你可能不耐烦了,再忍忍,快结束了哈!

进入到AbstractAutowireCapableBeanFactory#populateBean(beanName, mbd, instanceWrapper)方法看一下

AutowiredAnnotationBeanPostProcessor 中的 postProcessProperties 方法

这里获取的缓存就是前面set进去的

有没有发现这里的图似曾相识,没错!就是文章一开始的InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues() 处理过程,哦豁,首尾呼应了呢!

5.DestructionAwareBeanPostProcessor

1.postProcessBeforeDestruction(Object bean, String beanName) Bean销毁之前的回调方法,

其典型实现有ApplicationListenerDetector用于处理ApplicationListener的添加和销毁、InitDestroyAnnotationBeanPostProcessor用于处理@PostConstruct和@PreDestroy、ScheduledAnnotationBeanPostProcessor用于处理@Scheduled注解。

2、requiresDestruction()判断是否需要进行销毁,一般情况下都是需要的

实现类

1、ApplicationListenerDetector 处理ApplicationListener的添加和销毁

2、InitDestroyAnnotationBeanPostProcessor 处理@PostConstruct和@PreDestroy

3、ScheduledAnnotationBeanPostProcessor 处理@Scheduled注解

6、原生实现类

这里讲一下重点的实现类ApplicationContextAwareProcessor

如果实现了里面的aware接口,就能获取到对应的能力

7、注册时机

1.AbstractApplicationContext#refresh()

2.AbstractApplicationContextegister#BeanPostProcessors(beanFactory);

3.PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);

进入registerBeanPostProcessors()方法,代码如下:

public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

   // Register BeanPostProcessorChecker that logs an info message when
   // a bean is created during BeanPostProcessor instantiation, i.e. when
   // a bean is not eligible for getting processed by all BeanPostProcessors.
   // beanProcessorTargetCount表示BeanFactory中所有的BeanPostProcessor数量,+1表示BeanPostProcessorChecker
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   // Separate between BeanPostProcessors that implement PriorityOrdered,
   // Ordered, and the rest.
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
   List<String> orderedPostProcessorNames = new ArrayList<>();
   List<String> nonOrderedPostProcessorNames = new ArrayList<>();
   for (String ppName : postProcessorNames) {
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
         priorityOrderedPostProcessors.add(pp);
         if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
         }
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   // First, register the BeanPostProcessors that implement PriorityOrdered.
   // 升序排序
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

   // Next, register the BeanPostProcessors that implement Ordered.
   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String ppName : orderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);

   // Now, register all regular BeanPostProcessors.
   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   for (String ppName : nonOrderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      nonOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

   // Finally, re-register all internal BeanPostProcessors.
   // MergedBeanDefinitionPostProcessor排在最后
   sortPostProcessors(internalPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, internalPostProcessors);

   // Re-register post-processor for detecting inner beans as ApplicationListeners,
   // moving it to the end of the processor chain (for picking up proxies etc).
   // ApplicationListenerDetector放在所有BeanPostProcessor之后,注意ApplicationListenerDetector的equals()方法实现
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

简单描述下:

1、该方法分别对实现了PriorityOrdered、Ordered和无顺序接口进行注册,而且MergedBeanDefinitionPostProcessor 接口还多添加了一次。

2、在代码的最后还添加了一个ApplicationListenerDetector()方法,用于获取容器中的ApplicationListener进行注册。

3、添加方法使用BeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor)。此时容器中已经保存的是BeanPostProcessor的实例,因为已经调用BeanFactory#getBean方法。

4、关于MergedBeanDefinitionPostProcessor接口,虽然通过internalPostProcessors重新添加了一次,但是并不会重复添加,因为addBeanPostProcessor方法是先remove,再add,这些BeanPostProcessor就会添加到最后。

最后:作为图灵学院一份子,学习来源于周瑜和徐庶两位我特别敬重的老师,站在巨人的肩膀上增加了自己的理解,本文不以商业化为目的,纯个人学习使用

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序源仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值