现象
在有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是不是有咱们自定义的注解,从而处理业务,就会失败。
关注公众号,回复:【代码的艺术】获取链接及提取码