You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@dubbo.apache.org by GitBox <gi...@apache.org> on 2018/09/08 17:19:19 UTC

[GitHub] lvhao opened a new issue #2473: AnnotationBean#postProcessBeanFactory方法异常处理不当引起部分Bean无法注册

lvhao opened a new issue #2473: AnnotationBean#postProcessBeanFactory方法异常处理不当引起部分Bean无法注册
URL: https://github.com/apache/incubator-dubbo/issues/2473
 
 
   ### Environment
   
   * Dubbo version: all
   * Operating System version: mac
   * Java version: jdk1.8
   
   ### Step to reproduce this issue
   由于AnnotationBean捕获了异常并未做适当处理,Spring容器正常启动,但此时容器内是丢失了部分Bean的。源码调用路径如下
   
   `Spring ClassPathBeanDefinitionScanner类`
   ```
   protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
   		for (String basePackage : basePackages) {
   			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
   			for (BeanDefinition candidate : candidates) {
   				...
                                    //  该方法判断bean是否已存在
                                    // checkCandidate发生异常后,注册流程终止,丢失部分Bean,异常上抛
   				if (checkCandidate(beanName, candidate)) {
   					...
   					registerBeanDefinition(definitionHolder, this.registry);
   				}
   			}
   		}
   		return beanDefinitions;
   	}
   
   // 如果不同的jar包里引入了同名Bean(例如SpringUtil),且各自实现不同不兼容,Spring判定为冲突,抛ConflictingBeanDefinitionException异常
   protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
   		if (!this.registry.containsBeanDefinition(beanName)) {
   			return true;
   		}
   		BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
   		BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
   		if (originatingDef != null) {
   			existingDef = originatingDef;
   		}
   		if (isCompatible(beanDefinition, existingDef)) {
   			return false;
   		}
                   // 有可能走到这里 
   		throw new ConflictingBeanDefinitionException("...");
   	}
   ```
   
   `Dubbo-config AnnotationBean类`
   ```
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
               throws BeansException {
           if (annotationPackage == null || annotationPackage.length() == 0) {
               return;
           }
           if (beanFactory instanceof BeanDefinitionRegistry) {
               try {
                   // init scanner
                   Class<?> scannerClass = ReflectUtils.forName("org.springframework.context.annotation.ClassPathBeanDefinitionScanner");
                   Object scanner = scannerClass.getConstructor(new Class<?>[] {BeanDefinitionRegistry.class, boolean.class}).newInstance(new Object[] {(BeanDefinitionRegistry) beanFactory, true});
                   // add filter
                   Class<?> filterClass = ReflectUtils.forName("org.springframework.core.type.filter.AnnotationTypeFilter");
                   Object filter = filterClass.getConstructor(Class.class).newInstance(Service.class);
                   Method addIncludeFilter = scannerClass.getMethod("addIncludeFilter", ReflectUtils.forName("org.springframework.core.type.filter.TypeFilter"));
                   addIncludeFilter.invoke(scanner, filter);
                   // scan packages
                   String[] packages = Constants.COMMA_SPLIT_PATTERN.split(annotationPackage);
                   Method scan = scannerClass.getMethod("scan", new Class<?>[]{String[].class});
   
                 //  上层调用,异常在这处理
                   scan.invoke(scanner, new Object[] {packages});
               } catch (Throwable e) {
                   // spring 2.0
                   // 此处应该记录错误日志或者抛出异常告知应用
               }
           }
       }
   ```
   
   ### Expected Result
   
   期望继续抛出异常或者记录错误日志,便于问题定位。
   
   ### Actual Result
   表象为应用启动成功,日志里没有任何错误信息,但请求过来时会报错(手动从容器内获取bean).
   
   ```
   Just put your stack trace here!
   ```
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org