Package com.firefly.core

Source Code of com.firefly.core.AbstractApplicationContext

package com.firefly.core;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.firefly.core.support.BeanDefinition;
import com.firefly.core.support.exception.BeanDefinitionParsingException;
import com.firefly.utils.VerifyUtils;
import com.firefly.utils.log.Log;
import com.firefly.utils.log.LogFactory;

abstract public class AbstractApplicationContext implements ApplicationContext {

  private static Log log = LogFactory.getInstance().getLog("firefly-system");
  protected Map<String, Object> map = new HashMap<String, Object>();
  protected Set<String> errorMemo = new HashSet<String>();
  protected List<BeanDefinition> beanDefinitions;

  public AbstractApplicationContext() {
    this(null);
  }

  public AbstractApplicationContext(String file) {
    beanDefinitions = getBeanDefinitions(file);
    check(); //冲突检测
    addObjectToContext();
  }

  private void addObjectToContext() {
    for (BeanDefinition beanDefinition : beanDefinitions) {
      inject(beanDefinition);
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T getBean(Class<T> clazz) {
    return (T) map.get(clazz.getName());
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T getBean(String id) {
    return (T) map.get(id);
  }

  protected void check() {
    // TODO 需要增加测试用例
    // 1.id相同的抛异常
    // 2.className或者interfaceName相同,但其中一个没有定义id,抛异常
    // 3.className或者interfaceName相同,且都定义的id,需要保存备忘,按类型或者接口自动注入的时候抛异常

    for (int i = 0; i < beanDefinitions.size(); i++) {
      for (int j = i + 1; j < beanDefinitions.size(); j++) {
        log.debug("check bean " + i + "|" + j);
        BeanDefinition b1 = beanDefinitions.get(i);
        BeanDefinition b2 = beanDefinitions.get(j);

        if (VerifyUtils.isNotEmpty(b1.getId())
            && VerifyUtils.isNotEmpty(b2.getId())
            && b1.getId().equals(b2.getId())) {
          error("bean " + b1.getClassName() + " and bean "
              + b2.getClassName() + " have duplicate id ");
        }

        if (b1.getClassName().equals(b2.getClassName())) {
          if (VerifyUtils.isEmpty(b1.getId())
              || VerifyUtils.isEmpty(b2.getId())) {
            error("class " + b1.getClassName()
                + " duplicate definition");
          } else {
            errorMemo.add(b1.getClassName());
          }
        }

        for (String iname1 : b1.getInterfaceNames()) {
          for (String iname2 : b2.getInterfaceNames()) {
            if (iname1.equals(iname2)) {
              if (VerifyUtils.isEmpty(b1.getId())
                  || VerifyUtils.isEmpty(b2.getId())) {
                error("class " + b1.getClassName()
                    + " duplicate definition");
              } else {
                errorMemo.add(iname1);
              }
            }
          }
        }

      }
    }
  }

  protected void check(String key) {
    if(errorMemo.contains(key)) {
      error(key + " auto inject failure!");
    }
  }

  protected void addObjectToContext(BeanDefinition beanDefinition) {
    // 增加声明的组件到 ApplicationContext
    Object object = beanDefinition.getObject();
    // 把id作为key
    String id = beanDefinition.getId();
    if (VerifyUtils.isNotEmpty(id))
      map.put(id, object);

    // 把类名作为key
    map.put(beanDefinition.getClassName(), object);

    // 把接口名作为key
    String[] keys = beanDefinition.getInterfaceNames();
    for (String k : keys) {
      map.put(k, object);
    }
  }

  protected BeanDefinition findBeanDefinition(String key) {
    check(key);
    BeanDefinition ret = null;
    for (BeanDefinition beanDefinition : beanDefinitions) {
      if (key.equals(beanDefinition.getId())) {
        ret = beanDefinition;
        break;
      } else if (key.equals(beanDefinition.getClassName())) {
        ret = beanDefinition;
        break;
      } else {
        for (String interfaceName : beanDefinition.getInterfaceNames()) {
          if (key.equals(interfaceName)) {
            ret = beanDefinition;
            break;
          }
        }
      }
    }
    return ret;
  }

  /**
   * 处理异常
   *
   * @param msg
   *            异常信息
   */
  protected void error(String msg) {
    log.error(msg);
    throw new BeanDefinitionParsingException(msg);
  }

  abstract protected List<BeanDefinition> getBeanDefinitions(String file);

  abstract protected Object inject(BeanDefinition beanDef);

}
TOP

Related Classes of com.firefly.core.AbstractApplicationContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.