spring cloud注解RefreshScope坑之:与BeanPostProcessor共用不处理

363 阅读1分钟

现象

在有spring注解Service、Component等spring自动扫描的类上加上注解 RefreshScope,使得自定义BeanPostProcessor无法处理。

一般我们会在此类上加上我们自定义的注解,结合BeanPostProcessor处理时会导致故障发生。

原因 我们来看一下BeanPostProcessor触发的时机: 源码位于: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); }

Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }

try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }

return wrappedBean; }

重点看第上面所显示代码25、26行:

图片

BeanPostProcessor的触发是需要条件的: mbd == null || !mbd.isSynthetic() bean定义为null容易理解;

/**

  • Return whether this bean definition is 'synthetic', that is,
  • not defined by the application itself. */ public boolean isSynthetic() { return this.synthetic; }

debug过程中,这个条件为true ,BeanPostProcessorhu会不处理。

那为什么加了RefreshScope注解这个条件为ture呢。

看一下注解的处理关键点: org.springframework.cloud.context.scope.refresh.RefreshScope

处理关键地方: org.springframework.cloud.context.scope.GenericScope#postProcessBeanDefinitionRegistry

@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { for (String name : registry.getBeanDefinitionNames()) { BeanDefinition definition = registry.getBeanDefinition(name); if (definition instanceof RootBeanDefinition) { RootBeanDefinition root = (RootBeanDefinition) definition; if (root.getDecoratedDefinition() != null && root.hasBeanClass() && root.getBeanClass() == ScopedProxyFactoryBean.class) { if (getName().equals(root.getDecoratedDefinition().getBeanDefinition() .getScope())) { root.setBeanClass(LockedScopedProxyFactoryBean.class); root.getConstructorArgumentValues().addGenericArgumentValue(this); // surprising that a scoped proxy bean definition is not already // marked as synthetic? root.setSynthetic(true); } } } } }

看上面代码的16行: 图片

注解RefreshScope处理bean注册的时候设置了true值:

root.setSynthetic(true);

总结

spring cloud注解RefreshScope与BeanPostProcessor共用,BeanPostProcessor不会处理此bean。

若是扩展BeanPostProcessor,自定义处理我们的bean,比如自定义注解,扩展BeanPostProcessor处理bean是不是有咱们自定义的注解,从而处理业务,就会失败。

关注公众号,回复:【代码的艺术】获取链接及提取码

转载:mp.weixin.qq.com/s?__biz=Mzg…