package h2o.common.thirdparty.spring.factory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.concurrent.locks.Lock;

public class SpringFactory implements BeanFactoryAware {
	
	private static final Lock lock = new java.util.concurrent.locks.ReentrantLock();

	private static volatile BeanFactory beanFactory;

	public  static void setStaticConfigPath(String... path) {
		lock.lock();
		try {
			beanFactory = new ClassPathXmlApplicationContext(path);
		} finally {
			lock.unlock();
		}	
	}
	
	public void setConfigPath(String... path) {
		setStaticConfigPath(path);
	}

    public void setBeanFactory(BeanFactory bf) throws BeansException {
        lock.lock();
        try {
            beanFactory = bf;
        } finally {
            lock.unlock();
        }
    }

    public static BeanFactory getBeanFactory()  {
        BeanFactory bf = beanFactory;
        if (bf == null) {
            lock.lock();
            try {
                bf = beanFactory;
                if (bf == null) {
                    setStaticConfigPath("/applicationContext.xml");
                    bf = beanFactory;
                }
            } finally {
                lock.unlock();
            }
        }
        return bf;
    }


	@SuppressWarnings("unchecked")
	public static <T> T getObject(String beanId) {
		
		return (T) getBeanFactory().getBean(beanId);
	}


	/*====== delegate =====*/


    public static Object getBean(String name) throws BeansException {
        return getBeanFactory().getBean(name);
    }

    public static <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return getBeanFactory().getBean(name, requiredType);
    }

    public static <T> T getBean(Class<T> requiredType) throws BeansException {
        return getBeanFactory().getBean(requiredType);
    }

    public static Object getBean(String name, Object... args) throws BeansException {
        return getBeanFactory().getBean(name, args);
    }


    public static boolean containsBean(String name) {
        return getBeanFactory().containsBean(name);
    }

    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().isSingleton(name);
    }

    public static boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().isPrototype(name);
    }

    public static boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
        return getBeanFactory().isTypeMatch(name, typeToMatch);
    }

    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getType(name);
    }

    public static String[] getAliases(String name) {
        return getBeanFactory().getAliases(name);
    }



}

@@ -348,16 +348,65 @@
 Context;
+%0Aimport org.springframework.stereotype.Component;
 %0A%0Aimport
@@ -440,16 +440,27 @@
 .Lock;%0A%0A
+@Component%0A
 public c
@@ -1197,32 +1197,33 @@
 ry;%0A        if (
+ 
 bf == null) %7B%0A  
@@ -1208,32 +1208,33 @@
  if ( bf == null
+ 
 ) %7B%0A            
@@ -1237,299 +1237,71 @@
     
-lock.lock();%0A            try %7B%0A                bf = beanFactory;%0A                if (bf == null) %7B%0A                    setStaticConfigPath(%22/applicationContext.xml%22);%0A                    bf = beanFactory;%0A                %7D%0A            %7D finally %7B%0A                lock.unlock();%0A            %7D
+throw new IllegalStateException(%22BeanFactory not initialized%22);
 %0A   

解决 Spring boot 下不能初始化问题