一、UML类图分析说明
如下图定义Sar微服务组件的完整的类之间依赖关系图,核心类SARContextBean,其中通过其组成的成员类加载器、基础SARAttrs、上下文ServletContext/SpringContext及分发器Dispatcher主要部分
关于组件SAR提供了独立的配置文件、类加载器、Spring容器及热部署和热插拔的基本特征属性
二、核心类代码
1. 主要核心类SARContextBean,完成所有组件定义实现,具体代码如下所示
import com.xwood.woopa.app.biz.ac.ApplicationController;@b@import com.xwood.woopa.app.biz.ac.ApplicationControllerException;@b@import com.xwood.woopa.app.dto.ServiceRequest;@b@import com.xwood.woopa.app.dto.ServiceResponse;@b@import com.xwood.woopa.papp.PAppException;@b@import com.xwood.woopa.papp.esa.ESADefinition;@b@import com.xwood.woopa.papp.sar.context.SARSpringContextFactory;@b@import com.xwood.woopa.papp.sar.event.SARShutdownEvent;@b@import com.xwood.woopa.papp.sar.event.SARStartupedEvent;@b@import com.xwood.woopa.papp.web.WebDispatcher;@b@import com.xwood.woopa.pizza.classloader.ClassLoaderStack;@b@import java.rmi.RemoteException;@b@import java.util.Collection;@b@import java.util.concurrent.locks.Lock;@b@import java.util.concurrent.locks.ReentrantLock;@b@import javax.servlet.ServletContext;@b@import javax.servlet.ServletException;@b@import javax.servlet.http.HttpServletRequest;@b@import javax.servlet.http.HttpServletResponse;@b@import org.apache.commons.logging.Log;@b@import org.apache.commons.logging.LogFactory;@b@import org.springframework.context.ConfigurableApplicationContext;@b@import org.springframework.core.Ordered;@b@@b@public final class SARContextBean@b@ implements SARContext, Ordered@b@{@b@ private String sarName;@b@ private volatile SARAttrs attrs;@b@ private volatile ConfigurableApplicationContext springContext;@b@ private volatile SARDispatcher dispatcher;@b@ private volatile ClassLoader classLoader;@b@ private volatile ConfigurableApplicationContext pappSpringContext;@b@ private volatile boolean running;@b@ private volatile WebDispatcher webDispatcher;@b@ private volatile ServletContext servletContext;@b@ private final Lock lock = new ReentrantLock();@b@ private Log logger = LogFactory.getLog(super.getClass());@b@@b@ public SARContextBean(SARAttrs attrs, ClassLoader classLoader, ConfigurableApplicationContext pappSpringContext, ServletContext servletContext)@b@ {@b@ this.attrs = attrs;@b@ this.sarName = attrs.getSarName();@b@ this.pappSpringContext = pappSpringContext;@b@ this.classLoader = classLoader;@b@ this.servletContext = servletContext;@b@ }@b@@b@ public boolean isRunning()@b@ {@b@ return this.running;@b@ }@b@@b@ public String getSARName()@b@ {@b@ return this.sarName;@b@ }@b@@b@ public boolean startup()@b@ {@b@ String sarName = this.sarName;@b@ this.lock.lock();@b@ try {@b@ if (this.running) {@b@ throw new PAppException("SAR:" + sarName + " be running.");@b@ }@b@@b@ if (this.logger.isInfoEnabled())@b@ this.logger.info("SAR<" + sarName + ">startup...");@b@@b@ long t1 = System.nanoTime();@b@@b@ Thread.currentThread().setContextClassLoader(this.classLoader);@b@@b@ SARSpringContextFactory context = new SARSpringContextFactory();@b@ this.springContext = context.create(this.pappSpringContext, this.classLoader, this.attrs, this.servletContext);@b@@b@ this.dispatcher = context.getDispatcher();@b@ this.webDispatcher = context.getWebDispatcher();@b@@b@ SARStartupedEvent event = new SARStartupedEvent(this);@b@@b@ this.springContext.publishEvent(event);@b@ if (this.logger.isInfoEnabled()) {@b@ this.logger.info("SAR<" + sarName + ">startup completed, times=" + ((System.nanoTime() - t1) / 1000L / 1000.0D) + "ms.");@b@ }@b@@b@ this.running = true;@b@ } catch (Throwable th) {@b@ this.logger.error("SAR<" + sarName + ">startup failed,cause:\n" + th.getLocalizedMessage(), th);@b@@b@ this.running = false;@b@ } finally {@b@ this.lock.unlock();@b@ }@b@ return this.running;@b@ }@b@@b@ public void shutdown() {@b@ this.lock.lock();@b@ try {@b@ innerShutdown();@b@ } finally {@b@ this.running = false;@b@ this.lock.unlock();@b@ }@b@ }@b@@b@ public Collection<ESADefinition> getESADefinitions()@b@ {@b@ if (this.dispatcher != null)@b@ return this.dispatcher.getESADefinitions();@b@@b@ return null;@b@ }@b@@b@ protected void innerShutdown() {@b@ String sarName = this.sarName;@b@ if (this.logger.isInfoEnabled())@b@ this.logger.info("SAR<" + sarName + ">shutdown now.");@b@@b@ if (this.springContext != null) {@b@ SARShutdownEvent event = new SARShutdownEvent(this);@b@@b@ this.springContext.publishEvent(event);@b@ }@b@ try {@b@ if (this.springContext != null)@b@ this.springContext.close();@b@ }@b@ catch (Throwable th) {@b@ this.logger.error("SAR<" + sarName + ">shutdown error,cause:\n" + th.getLocalizedMessage(), th);@b@ }@b@@b@ this.webDispatcher = null;@b@ this.dispatcher = null;@b@ this.classLoader = null;@b@ this.pappSpringContext = null;@b@ if (this.logger.isInfoEnabled())@b@ this.logger.info("SAR<" + sarName + ">shutdown completed.");@b@ }@b@@b@ public boolean handleWebRequest(HttpServletRequest request, HttpServletResponse response)@b@ throws ServletException@b@ {@b@ try@b@ {@b@ if (this.classLoader != null)@b@ ClassLoaderStack.push(this.classLoader);@b@@b@ int i = ((this.webDispatcher != null) && (this.webDispatcher.handleRequest(request, response))) ? 1 : 0;@b@@b@ return i;@b@ }@b@ finally@b@ {@b@ if (this.classLoader != null)@b@ ClassLoaderStack.pop();@b@ }@b@ }@b@@b@ public ServiceResponse handleRequest(ServiceRequest request)@b@ throws ApplicationControllerException, RemoteException@b@ {@b@ try@b@ {@b@ if (this.classLoader != null)@b@ ClassLoaderStack.push(this.classLoader);@b@@b@ ServiceResponse localServiceResponse = getDispatcher().handleRequest(request);@b@@b@ return localServiceResponse;@b@ }@b@ finally@b@ {@b@ if (this.classLoader != null)@b@ ClassLoaderStack.pop();@b@ }@b@ }@b@@b@ public ConfigurableApplicationContext getSpringContext()@b@ {@b@ return this.springContext;@b@ }@b@@b@ public ApplicationController getDispatcher() {@b@ return this.dispatcher;@b@ }@b@@b@ public WebDispatcher getWebDispatcher() {@b@ return this.webDispatcher;@b@ }@b@@b@ public int getOrder()@b@ {@b@ return this.attrs.getOrder();@b@ }@b@}
2. 工厂类SARContextFactoryBean,代码如下所示
import com.xwood.woopa.papp.lib.HomeDirectory;@b@import com.xwood.woopa.papp.sar.lib.SARClassLoaderFactory;@b@import com.xwood.woopa.pizza.utils.PizzaProperties;@b@import javax.servlet.ServletContext;@b@import org.apache.commons.logging.Log;@b@import org.apache.commons.logging.LogFactory;@b@import org.springframework.beans.BeansException;@b@import org.springframework.context.ApplicationContext;@b@import org.springframework.context.ApplicationContextAware;@b@import org.springframework.context.ConfigurableApplicationContext;@b@import org.springframework.web.context.ServletContextAware;@b@@b@public class SARContextFactoryBean@b@ implements SARContextFactory, ApplicationContextAware, ServletContextAware@b@{@b@ private static final String KEY_PREFIX_CONFIG = ".properties";@b@ private HomeDirectory pappHomeDirectory;@b@ private ConfigurableApplicationContext pappSpringContext;@b@ private Log logger;@b@ private ServletContext servletContext;@b@@b@ public SARContextFactoryBean()@b@ {@b@ this.logger = LogFactory.getLog(super.getClass());@b@ }@b@@b@ public SARContext create(String sarName) {@b@ PizzaProperties properties = new PizzaProperties("sar/" + sarName + ".properties");@b@@b@ if (this.logger.isInfoEnabled()) {@b@ this.logger.info("SAR:" + sarName + " configure properties=" + properties);@b@ }@b@@b@ SARAttrs attrs = new SARAttrs(sarName, properties);@b@ SARClassLoaderFactory classloaderFactory = new SARClassLoaderFactory(attrs, this.pappHomeDirectory.getRootDirectory());@b@@b@ ClassLoader classLoader = classloaderFactory.createClassLoader(this.pappSpringContext.getClassLoader());@b@@b@ return new SARContextBean(attrs, classLoader, this.pappSpringContext, this.servletContext);@b@ }@b@@b@ public void setApplicationContext(ApplicationContext applicationContext)@b@ throws BeansException@b@ {@b@ this.pappSpringContext = ((ConfigurableApplicationContext)applicationContext);@b@ }@b@@b@ public HomeDirectory getPappHomeDirectory() {@b@ return this.pappHomeDirectory;@b@ }@b@@b@ public void setPappHomeDirectory(HomeDirectory pappHomeDirectory) {@b@ this.pappHomeDirectory = pappHomeDirectory;@b@ }@b@@b@ public void setServletContext(ServletContext servletContext)@b@ {@b@ this.servletContext = servletContext;@b@ }@b@}