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

titan.lightbatis.mapper.SpringBootBindUtil Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/**
 * 
 */
package titan.lightbatis.mapper;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author [email protected]
 *
 */
public class SpringBootBindUtil {

    public static final IBind BIND;

    static {
        IBind bind;
        try {
            //boot2
            Class.forName("org.springframework.boot.context.properties.bind.Binder");
            bind = new SpringBoot2Bind();
        } catch (Exception e) {
            //boot1
            bind = new SpringBoot1Bind();
        }
        BIND = bind;
    }

    public static  T bind(Environment environment, Class targetClass, String prefix) {
        return BIND.bind(environment, targetClass, prefix);
    }

    public interface IBind {
         T bind(Environment environment, Class targetClass, String prefix);
    }

    /**
     * 使用 Spring Boot 1.x 方式绑定
     */
    public static class SpringBoot1Bind implements IBind {
        @Override
        public  T bind(Environment environment, Class targetClass, String prefix) {
            /**
             为了方便以后直接依赖 Spring Boot 2.x 时不需要改动代码,这里也使用反射
             try {
             RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment);
             Map properties = resolver.getSubProperties("");
             T target = targetClass.newInstance();
             RelaxedDataBinder binder = new RelaxedDataBinder(target, prefix);
             binder.bind(new MutablePropertyValues(properties));
             return target;
             } catch (Exception e) {
             throw new RuntimeException(e);
             }
             下面是这段代码的反射实现
             */
            try {
                //反射提取配置信息
                Class resolverClass = Class.forName("org.springframework.boot.bind.RelaxedPropertyResolver");
                Constructor resolverConstructor = resolverClass.getDeclaredConstructor(PropertyResolver.class);
                Method getSubPropertiesMethod = resolverClass.getDeclaredMethod("getSubProperties", String.class);
                Object resolver = resolverConstructor.newInstance(environment);
                Map properties = (Map) getSubPropertiesMethod.invoke(resolver, "");
                //创建结果类
                T target = targetClass.newInstance();
                //反射使用 org.springframework.boot.bind.RelaxedDataBinder
                Class binderClass = Class.forName("org.springframework.boot.bind.RelaxedDataBinder");
                Constructor binderConstructor = binderClass.getDeclaredConstructor(Object.class, String.class);
                Method bindMethod = binderClass.getMethod("bind", PropertyValues.class);
                //创建 binder 并绑定数据
                Object binder = binderConstructor.newInstance(target, prefix);
                bindMethod.invoke(binder, new MutablePropertyValues(properties));
                return target;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 使用 Spring Boot 2.x 方式绑定
     */
    public static class SpringBoot2Bind implements IBind {
        @Override
        public  T bind(Environment environment, Class targetClass, String prefix) {
            /**
             由于不能同时依赖不同的两个版本,所以使用反射实现下面的代码
             Binder binder = Binder.get(environment);
             return binder.bind(prefix, targetClass).get();
             下面是这两行代码的完全反射版本
             */
            try {
                Class bindClass = Class.forName("org.springframework.boot.context.properties.bind.Binder");
                Method getMethod = bindClass.getDeclaredMethod("get", Environment.class);
                Method bindMethod = bindClass.getDeclaredMethod("bind", String.class, Class.class);
                Object bind = getMethod.invoke(null, environment);
                Object bindResult = bindMethod.invoke(bind, prefix, targetClass);
                Method resultGetMethod = bindResult.getClass().getDeclaredMethod("get");
                Method isBoundMethod = bindResult.getClass().getDeclaredMethod("isBound");
                if ((Boolean) isBoundMethod.invoke(bindResult)) {
                    return (T) resultGetMethod.invoke(bindResult);
                }
                return null;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy