现在的位置: 首页 > 综合 > 正文

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

2013年10月02日 ⁄ 综合 ⁄ 共 8577字 ⁄ 字号 评论关闭

相对于客户端,服务器端工作就比较多了。服务器端需要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,否则直接扫描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 {
					  //没有注解则默认扫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的某个方法。

抱歉!评论已关闭.