All Downloads are FREE. Search and download functionalities are using the official Maven repository.

vip.justlive.oxygen.ioc.store.DefaultBeanStore Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package vip.justlive.oxygen.ioc.store;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import vip.justlive.oxygen.core.exception.Exceptions;

/**
 * bean存储
 *
 * @author wubo
 * @since 2.0.0
 */
public class DefaultBeanStore implements BeanStore {

  private final Set beans = new HashSet<>(32);
  private final ConcurrentMap, List> beanClassMap = new ConcurrentHashMap<>(32);
  private final ConcurrentMap beanNameMap = new ConcurrentHashMap<>(32);

  @Override
  public void addBean(String name, Object bean, int order) {
    if (beans.add(bean)) {
      Object oldVal = beanNameMap.putIfAbsent(name, bean);
      if (oldVal != null) {
        throw Exceptions.fail(String.format("[%s]名称[%s]已被[%s]占用", bean, name, oldVal));
      }
      BeanInfo beanInfo = new BeanInfo(name, bean, order);
      margeSuperClass(beanInfo);
    }
  }

  @Override
  public Object getBean(String name) {
    return beanNameMap.get(name);
  }

  @Override
  public  T getBean(Class clazz) {
    List beanInfos = beanClassMap.get(clazz);
    if (beanInfos == null) {
      return null;
    }
    Collections.sort(beanInfos);
    BeanInfo beanInfo = beanInfos.get(0);
    if (beanInfos.size() > 1 && beanInfo.getOrder() == Integer.MAX_VALUE) {
      throw Exceptions.fail(String.format("存在多个该类型的bean [%s]", beanInfos));
    }
    return clazz.cast(beanInfo.getBean());
  }

  @Override
  public  T getBean(String name, Class clazz) {
    return clazz.cast(getBean(name));
  }

  @Override
  public Map getBeanMap(Class clazz) {
    List beanInfos = beanClassMap.get(clazz);
    if (beanInfos == null) {
      return null;
    }
    Map map = new HashMap<>(beanInfos.size());
    beanInfos.forEach(beanInfo -> map.put(beanInfo.getName(), beanInfo.getBean()));
    return map;
  }

  @Override
  public  Map getCastBeanMap(Class clazz) {
    List beanInfos = beanClassMap.get(clazz);
    if (beanInfos == null) {
      return null;
    }
    Map map = new HashMap<>(beanInfos.size());
    beanInfos.forEach(beanInfo -> map.put(beanInfo.getName(), clazz.cast(beanInfo.getBean())));
    return map;
  }

  @Override
  public  List getBeanList(Class clazz) {
    List beanInfos = beanClassMap.get(clazz);
    List list = new ArrayList<>();
    if (beanInfos == null) {
      return list;
    }
    for (BeanInfo beanInfo : beanInfos) {
      list.add(clazz.cast(beanInfo.getBean()));
    }
    return list;
  }

  @Override
  public Collection getBeans() {
    return Collections.unmodifiableCollection(beans);
  }

  @Override
  public Set getBeanNames() {
    return beanNameMap.keySet();
  }

  @Override
  public void clean() {
    beanClassMap.clear();
    beanNameMap.clear();
    beans.clear();
  }

  private void setBean(Class clazz, BeanInfo beanInfo) {
    beanClassMap.computeIfAbsent(clazz, k -> new LinkedList<>()).add(beanInfo);
  }

  private void margeSuperClass(BeanInfo beanInfo) {
    Class clazz = beanInfo.getBean().getClass();
    do {
      setBean(clazz, beanInfo);
      mergeInterface(clazz, beanInfo);
      clazz = clazz.getSuperclass();
    } while (clazz != null && clazz != Object.class);
  }

  private void mergeInterface(Class clazz, BeanInfo beanInfo) {
    Class[] interfaces = clazz.getInterfaces();
    for (Class inter : interfaces) {
      if (!inter.getName().startsWith("java")) {
        setBean(inter, beanInfo);
      }
    }
  }

}