
com.taobao.hsf.standalone.HSFStarter Maven / Gradle / Ivy
The newest version!
package com.taobao.hsf.standalone;
import com.taobao.hsf.standalone.sar.HSFSarUtil;
import com.taobao.hsf.standalone.util.Constant;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;
/**
* 启动hsf容器,并通过HSFSpringConsumer/HSFSpringProvider和外界搭上联系,让hsf为应用服务
* HSFContainer中的ThirdContainerClassLoader就是该类的classloader
*
* @author [email protected]
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class HSFStarter {
private static Map> exportedClassMap;
public static void startFromPropertyValue(String propertyName) {
String sarPath = System.getProperty(propertyName);
if (sarPath == null) {
sarPath = System.getenv(propertyName);
}
if (sarPath == null) {
throw new RuntimeException("没有设定变量[" + propertyName + "]的值");
}
try {
start(sarPath);
} catch (Exception e) {
throw new RuntimeException("start hsf fail.", e);
}
}
/**
* 从user.home/.hsf/release/taobao-hsf.sar启动hsf
*/
public static void startFromHsfHome() {
String sarPath = System.getProperty("user.home") + "/.hsf/release/";
try {
start(sarPath);
} catch (Exception e) {
throw new RuntimeException("start hsf fail.", e);
}
}
public static void start(String sarPath) throws Exception {
start(sarPath, HSFStarter.class.getClassLoader());
}
/**
* 太多反射,如果要转包异常抛出去的话,很难看
*
* @param sarPath taobao-hsf.sar的路径,e.g. /Users/xiaozi/lightapi/release/taobao-hsf.sar
* @throws Exception
*/
public static void start(String sarPath, ClassLoader bizClassLoader) throws Exception {
URL[] sarJars = HSFSarUtil.listSarJar(sarPath);
if(sarJars == null || sarJars .length == 0) {
throw new RuntimeException("Build jars from sar failed.Please delete the directory of taobao-hsf.sar and re-start.");
}
// 判断HSF是1.x or 2.x
decideVersion(sarJars);
URLClassLoader hsfParentLoader =
new URLClassLoader(sarJars, HSFStarter.class.getClassLoader()) {
/*HSFContainer依赖log4j,导致不能完全和AppClassLoader隔离开*/
/**
* Pandora已经不依赖log4j了
* @param name
* @param resolve
* @return
* @throws ClassNotFoundException
*/
public synchronized Class> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
Class> clazz = null;
clazz = findLoadedClass(name);
if (clazz != null) {
if (resolve) resolveClass(clazz);
return (clazz);
}
// osgi 的类要优先使用自己的,不要能用应用的
if (name.startsWith("org.eclipse") || name.startsWith("org.osgi")) {
try {
clazz = findClass(name);
if (clazz != null) {
if (resolve) resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
// Ignore
}
}
return super.loadClass(name, resolve);
}
};
Class containerClass =
Class.forName("com.taobao.hsf.container.HSFContainer", true, hsfParentLoader);
Method startMethod = containerClass.getMethod("start", String[].class);
startMethod.invoke(null, new Object[]{new String[]{sarPath}});
// hsf2.x必须要先启动,然后再设置应用类加载器
Method setThirdContainerClassLoaderMethod =
containerClass.getMethod("setThirdContainerClassLoader", ClassLoader.class);
setThirdContainerClassLoaderMethod.invoke(null, bizClassLoader);
// 等待下启动吧。。。
Thread.sleep(5000);
Method getExportedClassesMethod =
containerClass.getMethod("getExportedClasses", (Class[]) null);
exportedClassMap =
(Map>) getExportedClassesMethod.invoke(null, (Object[]) null);
if (exportedClassMap.size() < 5) {
System.out.println("hsfstarter.log:exportedClassMap.size() < 5 !");
}
ClassLoader osgiLoader =
exportedClassMap.get("com.taobao.hsf.app.spring.util.HSFSpringConsumerBean")
.getClassLoader();
if (Constant.main_version == 1) {
// 等待processService被DS注入
Class serviceHolderClazz =
Class.forName("com.taobao.hsf.app.spring.util.HSFServiceHolderComponent", true,
osgiLoader);
long startTime = System.currentTimeMillis();
Object processService =
invokeStaticMethodWithoutParam(serviceHolderClazz, "getProcessService");
while (processService == null) {
Thread.sleep(200);
if (System.currentTimeMillis() - startTime > 3000) {
break;
}
processService = invokeStaticMethodWithoutParam(serviceHolderClazz, "getProcessService");
}
if (processService == null) {
throw new IllegalStateException("HSFServiceHolderComponent.getProcessService() return null");
}
startTime = System.currentTimeMillis();
Object configService = invokeReadField(processService, "configService");
while (configService == null) {
Thread.sleep(200);
if (System.currentTimeMillis() - startTime > 3000) {
break;
}
configService = invokeReadField(processService, "configService");
}
if(configService != null)
setConfigServiceRunModeToTest(configService);
} else {
// 2.x是不需要等待注入的,但是保留这行代码算是验证包是否正确
Class.forName("com.taobao.hsf.util.HSFServiceContainer", true, osgiLoader);
}
}
/**
* export出去的类及其产生的instance可能被外部hold住
*
* @return
*/
public static Class> getHSFSpringConsumerBean() {
return exportedClassMap.get("com.taobao.hsf.app.spring.util.HSFSpringConsumerBean");
}
public static Class> getHSFSpringProviderBean() {
return exportedClassMap.get("com.taobao.hsf.app.spring.util.HSFSpringProviderBean");
}
/**
* 应用不需引入spring获取远程服务. hsf内部引用会用内部的spring.jar
*
* @param interfaceName
* @param version
* @return
*/
@Deprecated
public static Object getRemotingServiceWithoutSpring(String interfaceName, String version,
String group) {
Class realConsumerClass = getHSFSpringConsumerBean();
try {
Object realConsumer = realConsumerClass.newInstance();
Method stringSetter = realConsumerClass.getMethod("setInterfaceName", String.class);
stringSetter.invoke(realConsumer, new Object[]{interfaceName});
stringSetter = realConsumerClass.getMethod("setVersion", String.class);
stringSetter.invoke(realConsumer, new Object[]{version});
if (group != null) {
stringSetter = realConsumerClass.getMethod("setGroup", String.class);
stringSetter.invoke(realConsumer, new Object[]{group});
}
Method noParamMethod = realConsumerClass.getMethod("init");
noParamMethod.invoke(realConsumer, new Object[]{});
noParamMethod = realConsumerClass.getMethod("getObject");
return noParamMethod.invoke(realConsumer, new Object[]{});
} catch (Exception e) {
throw new RuntimeException("get service[" + interfaceName + "-" + version + "] fail", e);
}
}
@Deprecated
public static Object createProviderWithoutSpring(String interfaceName, String serviceVersion,
Object serviceInstance, Map stringSetterParam) {
Class providerBean = getHSFSpringProviderBean();
try {
Object realProvider = providerBean.newInstance();
Method stringSetter = providerBean.getMethod("setServiceInterface", String.class);
stringSetter.invoke(realProvider, new Object[]{interfaceName});
stringSetter = providerBean.getMethod("setServiceVersion", String.class);
stringSetter.invoke(realProvider, new Object[]{serviceVersion});
if (stringSetterParam != null) {
for (String methodName : stringSetterParam.keySet()) {
stringSetter = providerBean.getMethod(methodName, String.class);
stringSetter.invoke(realProvider, new Object[]{stringSetterParam.get(methodName)});
}
}
Method objSetter = providerBean.getMethod("setTarget", Object.class);
objSetter.invoke(realProvider, new Object[]{serviceInstance});
Method noParamMethod = providerBean.getMethod("init");
noParamMethod.invoke(realProvider, new Object[]{});
return realProvider;
} catch (Exception e) {
throw new RuntimeException("create service[" + interfaceName + "] fail", e);
}
}
private static Object invokeStaticMethodWithoutParam(Class clazz, String methodName)
throws Exception {
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);
return method.invoke(null, null);
}
private static Object invokeReadField(Object instance, String fieldName) throws Exception {
Class clazz = instance.getClass();
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(instance);
}
/**
* 设置运行模式为测试模式
*
* @param configService
* @throws Exception
*/
private static void setConfigServiceRunModeToTest(Object configService) throws Exception {
Method method = configService.getClass().getDeclaredMethod("setRunmode", int.class);
method.setAccessible(true);
method.invoke(configService, 0);
}
/**
* 通过sar/lib/下的包的名字是否包含pandora来判断hsf版本是1.x还是2.x
*
* @param sarJars
*/
private static void decideVersion(URL[] sarJars) {
for (URL url : sarJars) {
if (url.toString().contains("pandora")) {
// 2.x
Constant.main_version = 2;
return;
}
}
// 默认 1.x
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy