Spring源代码学习系列②BeanPostProcessor执行时机与实现原理

柔情只为你懂 2023-07-21 06:26 64阅读 0赞

这一篇主要学到了一种新的看源代码的方法。之前都是从最开始的代码开始,然后一步一步step into。这样会比较浪费时间,并且会因为代码多而容易搞混淆,抓不住重点。

这篇主要是看BeanPostProcessor的执行时机与相应的源代码,目前对于它是合适执行的,并不知道,但是可以明确的是我们继承的BeanPostProcessor一定会执行。因此可以完全将断点放在我们写的类MyBeanPostProcessor的函数里面。

看源码的另一种姿势

打开调试,进入断点。如下图所示:

format_png

然后逐帧查看其调用栈,慢慢找到关键代码:

format_png 1

初始化流程

主要的初始化流程包括:XXXAware方法执行、BeanPostProcessor.beforeXX()、InitilizingBean、initMethod、BeanPostProcessor.afterXX()。

format_png 2

执行AwareXX的顺序如下:

format_png 3

执行applyBeanPostProcessorsBeforeInitialization时,如果BeanPostProcessor返回的是null,那么将不会执行后续的BeanPostProcessor。

format_png 4

然后先执行InitializingBean,再调用自定义初始化方法initMethod。

format_png 5

最后执行BeanPostProcessor.afterXX(),与before的类似。

在Spring中的用途

先看两个比较简单的,会直接调用BeanPostProcessor的两个方法,达到spring的相应功能。

ApplicationContextAwareProcessor

在bean中,实现ApplicationContextAware接口,这个后置处理器会在bean初始化前,设置进ApplicationContext

  1. @Override
  2. @Nullable
  3. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  4. if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
  5. bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
  6. bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
  7. return bean;
  8. }
  9. AccessControlContext acc = null;
  10. if (System.getSecurityManager() != null) {
  11. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
  12. }
  13. if (acc != null) {
  14. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  15. invokeAwareInterfaces(bean);
  16. return null;
  17. }, acc);
  18. }
  19. else {
  20. invokeAwareInterfaces(bean);
  21. }
  22. return bean;
  23. }
  24. private void invokeAwareInterfaces(Object bean) {
  25. if (bean instanceof EnvironmentAware) {
  26. ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
  27. }
  28. if (bean instanceof EmbeddedValueResolverAware) {
  29. ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
  30. }
  31. if (bean instanceof ResourceLoaderAware) {
  32. ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
  33. }
  34. if (bean instanceof ApplicationEventPublisherAware) {
  35. ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
  36. }
  37. if (bean instanceof MessageSourceAware) {
  38. ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
  39. }
  40. if (bean instanceof ApplicationContextAware) {
  41. ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
  42. }
  43. }

BeanValidationPostProcessor

此方法默认在初始化数据之前进行数据校验。

  1. private boolean afterInitialization = false;
  2. @Override
  3. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  4. if (!this.afterInitialization) {
  5. doValidate(bean);
  6. }
  7. return bean;
  8. }
  9. @Override
  10. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  11. if (this.afterInitialization) {
  12. doValidate(bean);
  13. }
  14. return bean;
  15. }
  16. protected void doValidate(Object bean) {
  17. Assert.state(this.validator != null, "No Validator set");
  18. Object objectToValidate = AopProxyUtils.getSingletonTarget(bean);
  19. if (objectToValidate == null) {
  20. objectToValidate = bean;
  21. }
  22. Set<ConstraintViolation<Object>> result = this.validator.validate(objectToValidate);
  23. if (!result.isEmpty()) {
  24. StringBuilder sb = new StringBuilder("Bean state is invalid: ");
  25. for (Iterator<ConstraintViolation<Object>> it = result.iterator(); it.hasNext();) {
  26. ConstraintViolation<Object> violation = it.next();
  27. sb.append(violation.getPropertyPath()).append(" - ").append(violation.getMessage());
  28. if (it.hasNext()) {
  29. sb.append("; ");
  30. }
  31. }
  32. throw new BeanInitializationException(sb.toString());
  33. }
  34. }

InitDestroyAnnotationBeanPostProcessor

执行被@PostConstruct@PreDestroy注解的方法,参与生命周期。

初始化方法执行

@PostConstruct执行过程比较直接,因为此类直接实现了BeanPostProcessor的初始化方法。

  1. @Override
  2. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  3. LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
  4. try {
  5. // 执行初始化方法
  6. metadata.invokeInitMethods(bean, beanName);
  7. }
  8. catch (InvocationTargetException ex) {
  9. throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
  10. }
  11. catch (Throwable ex) {
  12. throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
  13. }
  14. return bean;
  15. }
  16. @Override
  17. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  18. return bean;
  19. }

具体的初始化方法如下:

  1. public void invokeInitMethods(Object target, String beanName) throws Throwable {
  2. Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
  3. Collection<LifecycleElement> initMethodsToIterate =
  4. (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
  5. if (!initMethodsToIterate.isEmpty()) {
  6. for (LifecycleElement element : initMethodsToIterate) {
  7. if (logger.isTraceEnabled()) {
  8. logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
  9. }
  10. element.invoke(target);
  11. }
  12. }
  13. }

寻找bean中初始化、销毁方法

所有的checkedInitMethods来自对initMethods中函数的遍历。包括destroy方法也是类似的。

  1. public void checkConfigMembers(RootBeanDefinition beanDefinition) {
  2. Set<LifecycleElement> checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
  3. for (LifecycleElement element : this.initMethods) {
  4. String methodIdentifier = element.getIdentifier();
  5. if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
  6. beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
  7. checkedInitMethods.add(element);
  8. if (logger.isTraceEnabled()) {
  9. logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
  10. }
  11. }
  12. }
  13. Set<LifecycleElement> checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
  14. for (LifecycleElement element : this.destroyMethods) {
  15. String methodIdentifier = element.getIdentifier();
  16. if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
  17. beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
  18. checkedDestroyMethods.add(element);
  19. if (logger.isTraceEnabled()) {
  20. logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
  21. }
  22. }
  23. }
  24. this.checkedInitMethods = checkedInitMethods;
  25. this.checkedDestroyMethods = checkedDestroyMethods;
  26. }

只要是被@PostConstruct注解过的函数,都会被加入到initMethods中。destroy也类似。

  1. do {
  2. final List<LifecycleElement> currInitMethods = new ArrayList<>();
  3. final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
  4. ReflectionUtils.doWithLocalMethods(targetClass, method -> {
  5. // 被initAnnotationType注解
  6. if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
  7. LifecycleElement element = new LifecycleElement(method);
  8. currInitMethods.add(element);
  9. if (logger.isTraceEnabled()) {
  10. logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
  11. }
  12. }
  13. // 被destroyAnnotationType注解
  14. if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
  15. currDestroyMethods.add(new LifecycleElement(method));
  16. if (logger.isTraceEnabled()) {
  17. logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
  18. }
  19. }
  20. });
  21. initMethods.addAll(0, currInitMethods);
  22. destroyMethods.addAll(currDestroyMethods);
  23. targetClass = targetClass.getSuperclass();
  24. }
  25. while (targetClass != null && targetClass != Object.class);
  26. return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
  27. new LifecycleMetadata(clazz, initMethods, destroyMethods));

具体的类型为:

init

format_png 6

destroy

format_png 7

销毁方法执行

@PreDestroy注解方法的执行,逻辑都放在了DisposableBeanAdapter中,它实现了DisposableBean

format_png 8

并实现了destroy()方法,执行所有的DestructionAwareBeanPostProcessor方法。

format_png 9

进入InitDestroyAnnotationBeanPostProcessorpostProcessBeforeDestruction,它完成了对所有的销毁方法的调用。

format_png 10

具体的执行销毁方法的逻辑与初始化类似

format_png 11

发表评论

表情:
评论列表 (有 0 条评论,64人围观)

还没有评论,来说两句吧...

相关阅读