docs: private Object getBeanFromBox(BeanBox box, boolean required, Set<Object> history) {// NOSONAR
  		// NOSONAR System.out.println(" Box=> box=" + box + " history=" + history);
  		BeanBoxException.assureNotNull(box, "Fail to build instance for a null beanBox");
  		Object bean = null;
  		if (box.isSingleton()) { // Check if singleton in cache
  			bean = singletonCache.get(box);
  			if (bean != null)
  				return bean;
  		}
  
  		if (box.isPureValue()) // if constant?
  			return box.getTarget();
  		if (box.getTarget() != null) {// if target?
  			if (EMPTY.class != box.getTarget())
  				return getBean(box.getTarget(), box.isRequired(), history);
  			if (box.getType() != null)
  				return getBean(box.getType(), box.isRequired(), history);
  			else
  				return notfoundOrException(box.getTarget(), box.isRequired());
  		}
  
  		boolean aopFound = false;// is AOP?
  		if (box.getAopRules() != null || box.getMethodAops() != null)
  			aopFound = true;
  		else if (this.getAopRules() != null && box.getBeanClass() != null)
  			for (Object[] aops : this.getAopRules()) // global AOP
  				if (BeanBoxUtils.nameMatch((String) aops[1], box.getBeanClass().getName())) {
  					aopFound = true;
  					break;
  				}
  		if (aopFound)
  			bean = AopUtils.createProxyBean(box.getBeanClass(), box, this);
  		else if (box.getCreateMethod() != null) // if have create method?
  			try {
  				Method m = box.getCreateMethod();
  				if (m.getParameterTypes().length == 1) {
  					bean = m.invoke(box, new Caller(this, required, history, null));
  				} else if (m.getParameterTypes().length == 0)
  					bean = m.invoke(box);
  				else
  					BeanBoxException.throwEX("Create method can only have 0 or 1 parameter");
  				BeanBoxException.assureNotNull(bean, "Create method created a null object.");
  			} catch (Exception e) {
  				return BeanBoxException.throwEX(e);
  			}
  		else if (box.getConstructor() != null) { // has constructor?
  			if (box.getConstructorParams() != null && box.getConstructorParams().length > 0) {
  				Object[] initargs = param2RealObjects(this, history, box.getConstructorParams());
  				try {
  					bean = box.getConstructor().newInstance(initargs);
  				} catch (Exception e) {
  					return BeanBoxException.throwEX(e);
  				}
  			} else // 0 param constructor
  				try {
  					bean = box.getConstructor().newInstance();
  				} catch (Exception e) {
  					return BeanBoxException.throwEX(e);
  				}
  		} else if (box.getBeanClass() != null) { // is normal bean
  			if (EMPTY.class == box.getBeanClass())
  				return notfoundOrException(EMPTY.class, required);
  			try {
  				bean = box.getBeanClass().newInstance();
  			} catch (Exception e) {
  				BeanBoxException.throwEX("Failed to call 0 parameter constructor of: " + box.getBeanClass(), e);
  			}
  		} else
  			return notfoundOrException(null, required); // return null or throw EX
  
  		// Now Bean is ready
  
  		// Cache bean or proxy bean right now for circular dependency use
  		if (box.isSingleton()) {
  			Object id = box.getSingletonId();
  			if (id != null)
  				singletonCache.put(box, bean);
  		} // NOW BEAN IS CREATED
  
  		if (box.getConfigMethod() != null) {// ====config method of this BeanBox
  			try {
  				Method m = box.getConfigMethod();
  				if (m.getParameterTypes().length == 2)
  					m.invoke(box, bean, new Caller(this, required, history, bean));
  				else if (m.getParameterTypes().length == 1)
  					m.invoke(box, bean);
  				else
  					BeanBoxException.throwEX("Config method can only have 1 or 2 parameters");
  			} catch (Exception e) {
  				return BeanBoxException.throwEX(e);
  			}
  		}
  
  		if (box.getPostConstruct() != null) // PostConstructor
  			ReflectionUtils.invokeMethod(box.getPostConstruct(), bean);
  
  		if (box.getFieldInjects() != null) // Fields inject
  			for (Entry<Field, BeanBox> entry : box.getFieldInjects().entrySet()) {
  				Field f = entry.getKey();
  				BeanBox b = entry.getValue();
  				Object fieldValue = this.getBeanFromBox(b, false, history);
  				if (EMPTY.class == fieldValue) {
  					if (b.isRequired())
  						BeanBoxException.throwEX("Not found required value for field: " + f.getName() + " in "
  								+ f.getDeclaringClass().getName());
  				} else {
  					if (fieldValue != null && fieldValue instanceof String)
  						fieldValue = this.valueTranslator.translate((String) fieldValue, b.getType());
  					ReflectionUtils.setField(f, bean, fieldValue);
  				}
  			}
  
  		if (box.getMethodInjects() != null) { // Methods inject
  			for (Entry<Method, BeanBox[]> methods : box.getMethodInjects().entrySet()) {
  				Method m = methods.getKey();
  				BeanBox[] paramBoxs = methods.getValue();
  				if (paramBoxs != null && paramBoxs.length > 0) {
  					Object[] methodParams = param2RealObjects(this, history, paramBoxs);
  					ReflectionUtils.invokeMethod(m, bean, methodParams);
  				} else // method has no parameter
  					ReflectionUtils.invokeMethod(m, bean);
  			}
  		}
  		return bean;
  	}