您的位置:首页 > 其它

Gaea源码阅读(三):服务端启动流程

2013-06-24 16:34 411 查看
相对于客户端,服务器端工作就比较多了。服务器端需要load jar包,利用fliter实现方法级的权限控制

// load service config
logger.info("load service config...");
ServiceConfig sc = loadServiceConfig(gaeaConfigDefaultPath, gaeaConfigPath);

// init class loader
logger.info("-----------------loading global jars------------------");
DynamicClassLoader classLoader = new DynamicClassLoader();
classLoader.addFolder(
rootPath + "service/deploy/" + sc.getString("gaea.service.name") + "/",
rootPath + "service/lib/",
rootPath + "lib"
);

//通过反射调用URLClassLoader的addURL方法
GlobalClassLoader.addSystemClassPathFolder(
rootPath + "service/deploy/" + sc.getString("gaea.service.name") + "/",
rootPath + "service/lib/",
rootPath + "lib"
);
logger.info("-------------------------end-------------------------\n");

if(new File(serviceFolderPath).isDirectory() || serviceName valid) {
// load proxy factory
logger.info("--------------------loading proxys-------------------");
IProxyFactory proxyFactory = ProxyFactoryLoader.loadProxyFactory(classLoader);
Global.getSingleton().setProxyFactory(proxyFactory);
logger.info("-------------------------end-------------------------\n");

// load init beans
logger.info("-----------------loading init beans------------------");
loadInitBeans(classLoader, sc);
logger.info("-------------------------end-------------------------\n");
}

// load global request-filters
logger.info("-----------loading global request filters------------");
List<IFilter> requestFilters = loadFilters(classLoader, sc, "gaea.filter.global.request");
for(IFilter filter : requestFilters) {
Global.getSingleton().addGlobalRequestFilter(filter);
}
logger.info("-------------------------end-------------------------\n");

// load global response-filters
logger.info("-----------loading global response filters-----------");
List<IFilter> responseFilters = loadFilters(classLoader, sc, "gaea.filter.global.response");
for(IFilter filter : responseFilters) {
Global.getSingleton().addGlobalResponseFilter(filter);
}
logger.info("-------------------------end-------------------------\n");

// load connection filters
logger.info("-----------loading connection filters-----------");
List<IFilter> connFilters = loadFilters(classLoader, sc, "gaea.filter.connection");
for(IFilter filter : connFilters) {
Global.getSingleton().addConnectionFilter(filter);
}
logger.info("-------------------------end-------------------------\n");

// load secureKey 当gaea.secure不为true时不启动权限认证
logger.info("------------------load secureKey start---------------------");
if(sc.getString("gaea.secure") != null && "true".equalsIgnoreCase(sc.getString("gaea.secure"))) {
logger.info("gaea.secure:" + sc.getString("gaea.secure"));
loadSecureKey(sc,serviceFolderPath);
}
logger.info("------------------load secureKey end----------------------\n");

// load servers
logger.info("------------------ starting servers -----------------");
loadServers(classLoader, sc);
logger.info("-------------------------end-------------------------\n");

// add current service file to monitor
if(sc.getBoolean("gaea.hotdeploy")) {
logger.info("------------------init file monitor-----------------");
addFileMonitor(rootPath, sc.getString("gaea.service.name"));
logger.info("-------------------------end-------------------------\n");
}


//load proxy factory

//ProxyFactoryLoader.loadProxyFactory
CreateManager cm = new CreateManager();
return cm.careteProxy(Global.getSingleton().getRootPath()
+ "service/deploy/"
+ ("gaea.service.name"),
classLoader);

// CreateManager.createProxy
//ContractInfo
if (file != null && file.exists()) {
//如果存在Serviceframe.xml
serviceContract = ContractConfig.loadContractInfo(configPath, classLoader);
} else {
//只扫描deploy/{serviceName}目录下的jar包
serviceContract = ScanClass.getContractInfo(serviceRootPath + "/", classLoader);
}


ServerContract是SessionBean的列表,SessionBean包括接口名,接口->实例Map,类信息。在Serviceframe.xml中可配置.

如果存在Serviceframe.xml,则扫描Serviceframe.xml,否则直接扫描jar包。

Serviceframe.xml的格式为:

<interface>
<class></class>
<lookup></lookup>
</interface>


// ScanClass.getContractInfo

//扫描注解,分别解析contract(接口),behavior(实现)
ServiceBehaviorbehavior = cls.getAnnotation(ServiceBehavior.class);
ServiceContract contract= cls.getAnnotation(ServiceContract.class);
if(behavior==null && contract == null) {
continue;
}

if(contract !=null) {
ClassInfo ci = contract(cls);
if(ci !=null) {
contractClassInfos.add(ci);
}
} elseif(behavior!= null) {
ClassInfo ci = behavior(cls);
if(ci !=null) {
behaviorClassInfos.add(ci);
}
}


//ScanClass.Contract()
//获取该类所有接口
List<Class<?>>interfaceList = getInterfaces(cls);
List<ClassInfo.MethodInfo>methodInfos = newArrayList<ClassInfo.MethodInfo>();

for(Class<?>interfaceCls : interfaceList) {
//接口所有方法
Method[]methods = interfaceCls.getDeclaredMethods();
if(contractAnn!=null && contractAnn.defaultAll()){
for(Methodm : methods) {
if(Modifier.isPublic(m.getModifiers())|| Modifier.isProtected(m.getModifiers())) {
ClassInfo.MethodInfo mi =newClassInfo.MethodInfo();
mi.setMethod(m);
methodInfos.add(mi);
}
}
}else {
//没有@ServiceContract注解则默认扫Public并OperationContract注解了的方法
for(Methodm : methods) {
if(Modifier.isPublic(m.getModifiers())|| Modifier.isProtected(m.getModifiers())) {
OperationContract oc =m.getAnnotation(OperationContract.class);
if(oc !=null) {
ClassInfo.MethodInfo mi =newClassInfo.MethodInfo();
mi.setMethod(m);
methodInfos.add(mi);
}
}
}
}
}

//ScanClass.behavior()
//扫描Method,如果发现HttpPathParameter注解,则加载RequestMapping。


//构造ContractInfo

//根据以上两步结果,构造ContractInfo
contractInfo =createContractInfo(contractClassInfos,behaviorClassInfos);
//构造过程
ContractInfocontractInfo = new ContractInfo();
List<SessionBean>sessionBeanList = newArrayList<SessionBean>();
for(ClassInfoc : contracts) {
SessionBeanbean = new SessionBean();
bean.setInterfaceClass(c);
bean.setInterfaceName(c.getCls().getName());
Map<String,String> implMap = newHashMap<String, String>();

//扫描和接口匹配的实现
for(ClassInfob : behaviors) {
Class<?>[]interfaceAry = b.getCls().getInterfaces();
for(Class<?>item : interfaceAry) {
if(item ==c.getCls()) {
implMap.put(b.getLookUP(),b.getCls().getName());
break;
}
}
}
bean.setInstanceMap(implMap);
sessionBeanList.add(bean);
}

contractInfo.setSessionBeanList(sessionBeanList);
return contractInfo;


//创建ProxyClass

List<ClassFile> localProxyList = new ProxyClassCreater().createProxy(classLoader, serviceContract, time);

//ProxyClassCreater.createProxy()
String proxyClassName = lookup + "ProxyStub" + time;

CtClass ctProxyClass = pool.makeClass(proxyClassName, null);

ctProxyClass.addInterface(localProxy); // IProxyStub接口

CtField proxyField = CtField.make( //构造实例
"private static " +sessionBean.getInterfaceName() +" serviceProxy = new " +implClassName +"();", ctProxyClass);

ctProxyClass.addField(proxyField);

//创建 method
for(Method m : uniqueMethodList) {
logger.debug("create method:" + m.getName());
String methodStr = createMethods(proxyClassName, m.getName(), allMethodList, uniqueNameList);
CtMethod methodItem = CtMethod.make(methodStr, ctProxyClass);
ctProxyClass.addMethod(methodItem);
}

//创建invoke方法
String invokeMethod = createInvoke(proxyClassName, uniqueNameList);
logger.debug("create invoke method:" + invokeMethod);
CtMethod invoke = CtMethod.make(invokeMethod, ctProxyClass);
ctProxyClass.addMethod(invoke);

clsList.add(new ClassFile(proxyClassName, ctProxyClass.toBytecode()));
}

//Invoke方法体,使用到了GaeaResponse和GaeaContext
private String createInvoke(String className, List<String> uniqueNameList) {
StringBuilder sb = new StringBuilder();
sb.append("public " + Constant.GAEARESPONSE_CLASS_NAME + " invoke(" + Constant.GAEACONTEXT_CLASS_NAME + " context) throws " + Constant.SERVICEFRAMEEXCEPTION_CLASS_NAME + " {");
sb.append("String methodName = ((" + Constant.REQUEST_PROTOCOL_CLASS_NAME + ")context.getGaeaRequest().getProtocol().getSdpEntity()).getMethodName();");
for (String methodName : uniqueNameList) {
sb.append("if(methodName.equalsIgnoreCase(\"");
sb.append(methodName);
sb.append("\")){return ");
sb.append(methodName);
sb.append("(context);}");
}
sb.append("throw new " + Constant.SERVICEFRAMEEXCEPTION_CLASS_NAME + "(\"method:" + className + ".invoke--msg:not found method (\"+methodName+\")\", context.getChannel().getRemoteIP(), context.getChannel().getLocalIP(), context.getGaeaRequest().getProtocol().getSdpEntity(), " + Constant.ERRORSTATE_CLASS_NAME + ".NotFoundMethodException, null);");
sb.append("}");
return sb.toString();
}


//创建ProxyFactory

ClassFile cfProxyFactory = new ProxyFactoryCreater().createProxy(classLoader, serviceContract, time);

IProxyFactory pfInstance = (IProxyFactory)constructor.newInstance(localProxyAry);
//constructor为ProxyFactory实例,里面初始化所有实例


//gaea.init的init方法

// load init beans
loadInitBeans(classLoader, sc);


//loadSecureKey最终将配置文件中//secure信息添加到Global.secureMap

loadSecureKey(sc,serviceFolderPath);


// load servers

loadServers(classLoader, sc);
//建立gaea.servers[].implement实例并调用start


主要工作总结如下:

解析gaea配置文件gaea_config.xml

添加jar包到系统Classloader

扫描deploy/{serviceName}下的jar包,根据@ServiceContract等注解建立实现类(SessionBean)和该实现类对应接口的映射关系。

创建SessionBean对应的代理ProxyStub,该代理类负责将调用转交给实现类,并在接口上对参数做一层包装。分别使用GaeaResponse和GaeaContext为返回、参数类型。

创建Proxy工厂类,包含了SessionBean实例。

加载Filter

加载SecureKey配置

调用配置文件gaea.init的方法

加载Server

Proxy工厂类其实是以后请求处理的入口,客户端请求经过包装后发送到服务器端,服务器端解析消息,Proxy工厂根据消息调用对应SessionBean的某个方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: