String Apath = "D:/work/ModelA/bin/"; 一定加“/”
String Bpath = "D:/work/ModelB/bin/";
URL aurl = new URL("file", "", -1, Apath);
URL burl = new URL("file", "", -1, Bpath);
URLClassLoader Aloader =new URLClassLoader(new URL[]{aurl});
URLClassLoader Bloader =new URLClassLoader(new URL[]{burl});
PluginCenter center =PluginCenter.getInstance();
center.putClassLoader("A", Aloader);
center.putClassLoader("B", Bloader);
IActivator i1 = (IActivator)Aloader.loadClass("com.a.AActivator").newInstance();
IActivator i2 = (IActivator)Bloader.loadClass("com.b.BActivator").newInstance();;
System.out.println(i1.getClass().getClassLoader());
System.out.println(i2.getClass().getClassLoader());
i1.init();
i2.init();
center.dispathNotice("A");
System.out.println(Inint.class.getClassLoader().getClass().getName());
System.out.println(Aloader.getParent().getClass().getName()); Aloader Bloader的父加载器是本类的加载器,所以A,B模块可以直接引用本模块的类
public class Application {
private Logger logger = LoggerManager.getLogger(Application.class);
private final LinkedHashSet<IApplicationListener> listeners = new LinkedHashSet<IApplicationListener>();
private final LinkedHashSet<IApplicationModule> modules = new LinkedHashSet<IApplicationModule>();
private ApplicationContext context;
private ApplicationControl control;
// 默认内置模块
{
install(Runtime.getRuntime().LISTENER);
install(new DataCenterModule());
}
/**
* 安装容器监听器,相同的监听器实例只会被安装一次,注意,listener 不能为NULL。
*
* @param listener
* 监听器实例
*/
protected void install(IApplicationListener listener) {
listeners.add(listener);
}
/**
* 安装模块,相同的模块只会被安装一次,注意,module不能为 NULL。
*
* @param module
*/
protected void install(IApplicationModule module) {
modules.add(module);
}
/**
* 启动运行容器。
*/
public void startup() {
logger.info("x Application starting...");
try {
createApplicationContext();
initialize(); // 初始化启动环境
// fire before startup
fireEvent(EventType.BEFORE_STARTUP);
// fire startup
fireEvent(EventType.STARTUP);
// fire after startup
fireEvent(EventType.AFTER_STARTUP);
} catch (Exception e) {
throw new RuntimeException(e);
}
logger.info(" Application start success");
System.out.println("服务已启动");
Thread shutdownHook = new Thread() {
public void run() {
shutdown();
}
};
java.lang.Runtime.getRuntime().addShutdownHook(shutdownHook);
synchronized (this) {
while (Runtime.getRuntime().getApplicationStatus() != Status.STOPPED) {
try {
wait();
} catch (InterruptedException e) {}
}
}
System.exit(0);
}
/**
* 关闭运行容器。
*/
public void shutdown() {
final Status status = Runtime.getRuntime().getApplicationStatus();
if (status != Status.RUNNING && status != Status.STARTING) {
logger.info(" Application isn't started");
return;
}
logger.info("Application stopping...");
try {
// fire before shutdown
fireEvent(EventType.BEFORE_SHUTDOWN);
// fire shutdown
// logger.info("Application is stopping");
fireEvent(EventType.SHUTDOWN);
// fire after shutdown
// logger.info("Application is stopped");
fireEvent(EventType.AFTER_SHUTDOWN);
} catch (Exception e) {
throw new RuntimeException(e);
}
logger.info("Application stop success");
System.out.println("服务已停止");
synchronized (this) {
this.notify();
}
}
public ApplicationContext getApplicationContext() {
return context;
}
/**
* 获取模块实例,指定参数为该模块的实现类,如果对应的模块不 存在或没有注册,则返回NULL。
*
* @param <T>
* 模块实现类泛型
* @param module
* 指定模块的实现类
* @return 模块实例,如果不存在或没有注册,返回NULL。
*/
public <T extends IApplicationModule> T getModule(Class<T> module) {
for (IApplicationModule m : modules) {
if (m.getClass() == module) {
return (T) m;
}
}
return null;
}
/**
* Application运行容器统一事件分发,根据EventType的类型分阶段分发事件,
* 事件分发顺序如下,分二阶段(启动、关闭),其中前置和后置事件由listener 负责处理,启动、关闭事件由module处理:
*
* 1. 启动 BEFORE_STARTUP STARTUP AFTER_STARTUP
*
* 2. 关闭 BEFORE_SHUTDOWN SHUTDOWN AFTER_SHUTDOWN
*
* @param type
* EventType事件类型
*/
private void fireEvent(EventType type) throws Exception {
ApplicationEvent event = new ApplicationEvent(type, context);
// fire "before event" to all listeners
for (IApplicationListener listener : listeners) {
switch (type) {
case BEFORE_STARTUP:
listener.beforeStartup(event);
break;
case BEFORE_SHUTDOWN:
listener.beforeShutdown(event);
break;
}
}
// do fire MODULES
for (IApplicationModule module : modules) {
switch (type) {
case STARTUP:
module.startup(event);
break;
case SHUTDOWN:
module.shutdown(event);
break;
}
}
// fire "after event" to all listeners
for (IApplicationListener listener : listeners) {
switch (type) {
case AFTER_STARTUP:
listener.afterStartup(event);
break;
case AFTER_SHUTDOWN:
listener.afterShutdown(event);
break;
}
}
}
/**
* 初始化运行容器,动态加载外挂模块
*
* @throws Exception
*/
protected void initialize() {
// do nothing
control = new ApplicationControl(this);
DataCenterConfig.load(); // 加载配置
}
public IApplicationControl getApplicationControl() {
return control;
}
/**
* 创建上下文信息。
*/
protected void createApplicationContext() {
if (context != null) {
return;
}
context = new ApplicationContext(this);
Runtime.getRuntime().setApplication(this);
Runtime.getRuntime().setApplicationContext(context);
}
public static void main(String[] args) {
Application application = new Application();
application.startup();
}
}
从配置文件实例化模型
public abstract class Service implements IService {
protected Logger logger = LoggerManager.getLogger(getClass());
private ServiceConfig config;
// 三个阶段
private final int inited = 0;
private final int started = 1;
private final int stopped = 2;
private int state = stopped;
public void setState(int state) {
this.state = state;
}
private int getState() {
return state;
}
public void init() {
try {
if (!isInited()) {
logger.info(String.format("service[%s] initializing", getName()));
initService();
logger.info(String.format("service[%s] initialized", getName()));
setState(inited);
}
} catch (Exception e) {
logger.log(Level.SEVERE, String.format("service[%s] init fail", getName()), e);
}
}
public void start() {
try {
if (!isStarted()) {
logger.info(String.format("service[%s] starting", getName()));
startService();
logger.info(String.format("service[%s] started", getName()));
setState(started);
}
} catch (Exception e) {
logger.log(Level.SEVERE, String.format("service[%s] start fail", getName()), e);
}
}
public void stop() {
try {
if (!isStopped()) {
logger.info(String.format("service[%s] stopping", getName()));
stopService();
logger.info(String.format("service[%s] stopped", getName()));
setState(stopped);
}
} catch (Exception e) {
logger.log(Level.SEVERE, String.format("service[%s] stop fail", getName()), e);
}
}
public boolean isInited() {
return getState() == inited || getState() == started;
}
public boolean isStarted() {
return getState() == started;
}
public boolean isStopped() {
return getState() == stopped;
}
public final String getClazz() {
return config.getClazz();
}
public final String getName() {
return config.getName();
}
public final ServiceConfig getServiceConfig() {
return config;
}
final void setServiceConfig(ServiceConfig config) {
this.config = config;
}
public String toString() {
return getName();
}
protected abstract void initService() throws ServiceException;
protected abstract void startService() throws ServiceException;
protected abstract void stopService() throws ServiceException;
}
lServiceLauncher launcher = new ServiceLauncher();launcher.startup();
public class ServiceLauncher implements IServiceLauncher {
private static final String DEFAULT_AGENT_XML = "service.xml";
private static Logger logger = LoggerManager.getLogger(ServiceLauncher.class);
private File configFile;
private List<Service> services;
private volatile boolean stop = false;
public static void main(String[] args) {
try {
ServiceLauncher launcher = new ServiceLauncher();
launcher.startup();
launcher.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
public void startup() throws Exception {
String configFileAttr = System.getProperty(DEFAULT_AGENT_XML);
if (configFileAttr != null) {
configFile = new File(configFileAttr);
} else {
File home = DataCenterConfig.getHome();
configFile = new File(home, "/config/" + DEFAULT_AGENT_XML);
}
startupService();
}
public void shutdown() throws Exception {
logger.info("stop services");
if (!stop) {
if (services != null)
for (IService service : services) {
service.stop();
}
}
ServiceFactory.clear();
logger.info("services stopped");
}
private void startupService() throws Exception {
try {
logger.info("start services");
constructService(); //构造实例
for (Service service : services) {
setServieProperties(service); //向实例注入参数
service.init();
}
for (Service service : services) {
if (service.isInited()){
service.start();
}
}
logger.info("servers started");
} catch (Exception e) {
logger.log(Level.SEVERE, "start fail", e);
throw e;
}
}
private void constructService() throws Exception {
services = new ArrayList<Service>();
ServiceParser serviceParser = new ServiceParser();
List<ServiceConfig> configs = serviceParser.getServiceConfigs(configFile);
for (ServiceConfig config : configs) {
Class clazz = Class.forName(config.getClazz());
Service service = (Service) clazz.newInstance();
service.setServiceConfig(config);
services.add(service);
ServiceFactory.registerService(service);
}
}
private void setServieProperties(IService service) throws Exception {
ServiceConfig config = service.getServiceConfig();
Class clazz = service.getClass();
for (String name : config.getAttributes().keySet()) {
Method method = getSetterMethod(clazz, name);
if (method != null) {
invokeSetterMethod(service, method, config, name);
} else {
Field field = getField(clazz, name);
if (field != null) {
setFieldValue(service, field, config, name);
}
}
}
}
private void setFieldValue(IService service, Field field, ServiceConfig config, String name) throws Exception {
try {
field.setAccessible(true);
Class parmType = field.getType();
setGlobalPropertyValue(config, name);
if (parmType.equals(Boolean.TYPE)) {
field.set(service, config.getBoolean(name));
} else if (parmType.equals(Integer.TYPE)) {
field.set(service, config.getInt(name));
} else if (parmType.equals(Long.TYPE)) {
field.set(service, config.getLong(name));
} else if (parmType.equals(Float.TYPE)) {
field.set(service, config.getFloat(name));
} else if (parmType.equals(Double.TYPE)) {
field.set(service, config.getDouble(name));
} else if (parmType.equals(String.class)) {
field.set(service, config.getString(name));
} else if (parmType.equals(File.class)) {
String path = config.getString(name);
if (path != null) {
File file = getAbsolutePath(path);
field.set(service, file);
}
} else if (Service.class.isAssignableFrom(parmType)) {
IService srv = ServiceFactory.getService(config.getString(name));
if (srv != null) {
field.set(service, srv);
}
} else {
throw new IllegalArgumentException("unsupport property type:" + parmType.getName() + "," + name);
}
} catch (Exception e) {
throw new Exception("set property error:" + name + " with service " + service.getName(), e);
}
}
private Field getField(Class<?> clazz, String name) throws Exception {
try {
Field field = clazz.getDeclaredField(name);
return field;
} catch (Exception e) {
throw new Exception("set property error:" + name, e);
}
}
private void invokeSetterMethod(IService service, Method method, ServiceConfig config, String name) throws Exception {
try {
Class parmType = method.getParameterTypes()[0];
setGlobalPropertyValue(config, name);
if (parmType.equals(Boolean.TYPE)) {
method.invoke(service, config.getBoolean(name));
} else if (parmType.equals(Integer.TYPE)) {
method.invoke(service, config.getInt(name));
} else if (parmType.equals(Long.TYPE)) {
method.invoke(service, config.getLong(name));
} else if (parmType.equals(Float.TYPE)) {
method.invoke(service, config.getFloat(name));
} else if (parmType.equals(Double.TYPE)) {
method.invoke(service, config.getDouble(name));
} else if (parmType.equals(String.class)) {
method.invoke(service, config.getString(name));
} else if (parmType.equals(File.class)) {
String path = config.getString(name);
if (path != null) {
File file = getAbsolutePath(path);
method.invoke(service, file);
}
} else if (Service.class.isAssignableFrom(parmType)) {
IService srv = ServiceFactory.getService(config.getString(name));
if (srv != null) {
method.invoke(service, srv);
}
} else {
throw new IllegalArgumentException("unsupport property type:" + parmType.getName() + "," + name);
}
} catch (Exception e) {
throw new Exception("set property error:" + name + " with service " + service.getName(), e);
}
}
private File getAbsolutePath(String path) {
File file = new File(path);
if (!file.isAbsolute()) {
file = new File(DataCenterConfig.getHome(), file.getPath());
}
return file;
}
private void setGlobalPropertyValue(ServiceConfig config, String name) {
String value = config.getAttribute(name);
if (value.startsWith("$") && value.length() > 1) {
String key = value.substring(1);
String trueValue = DataCenterConfig.getDatacenterConfig().getProperty(key);
config.put(name, trueValue);
}
}
/**
* 返回第一个遇到的合适的setter方法
*/
private Method getSetterMethod(Class clazz, String methodName) {
methodName = getSetterName(methodName);
for (Method method : clazz.getMethods()) {
if (method.getName().equals(methodName) && method.getReturnType() == void.class
&& !Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 1) {
return method;
}
}
return null;
}
private String getSetterName(String name) {
char firstChar = name.charAt(0);
name = "set" + Character.toUpperCase(firstChar) + "" + name.substring(1);
return name;
}
public class ServiceConfig {
private String clazz;
private String name;
private Map<String, String> attributes = new HashMap<String, String>();
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
public Map<String, String> getAttributes() {
return attributes;
}
public int getInt(String name) {
return Integer.valueOf(getAttribute(name));
}
public long getLong(String name) {
return Long.valueOf(getAttribute(name));
}
public String getString(String name) {
return getAttribute(name);
}
public float getFloat(String name) {
return Float.valueOf(getAttribute(name));
}
public double getDouble(String name) {
return Double.valueOf(getAttribute(name));
}
public boolean getBoolean(String name) {
return Boolean.valueOf(getAttribute(name));
}
public void put(String name, int value) {
attributes.put(name, String.valueOf(value));
}
public void put(String name, float value) {
attributes.put(name, String.valueOf(value));
}
public void put(String name, double value) {
attributes.put(name, String.valueOf(value));
}
public void put(String name, long value) {
attributes.put(name, String.valueOf(value));
}
public void put(String name, boolean value) {
attributes.put(name, String.valueOf(value));
}
public void put(String name, String value) {
attributes.put(name, value);
}
public String getAttribute(String name) {
return attributes.get(name);
}
public void putAttribute(String name, String value) {
attributes.put(name, value);
}
}
PluginManager manager = new PluginManager();
manager.init();
manager.start();
public class PluginManager {
protected Logger logger = LoggerManager.getLogger(getClass());
public static final String PLUGIN_LISTS_XML = "plugin-lists.xml";
private static final String XML_PLUGIN = "/plugins//plugin";
private File pluginsPath = new File(DataCenterConfig.getHome(), "plugins");
private Map<String, IPluginModule> plugins = new ConcurrentHashMap<String, IPluginModule>();
private static final List<IPluginActuator> startActuators = new LinkedList<IPluginActuator>();
private static final List<IPluginActuator> stopActuators = new LinkedList<IPluginActuator>();
static {
// 1. 创建执行器实例
ExtensionActuator extension = new ExtensionActuator();
ActivateActuator activate = new ActivateActuator();
// 2. 注册启动执行器
startActuators.add(extension);
startActuators.add(activate);
// 3. 注册关闭执行器
stopActuators.add(activate);
stopActuators.add(extension);
}
/**
* 初始化的时候安装所有的插件,插件可以被卸载
*/
public void init() throws Exception {
installPlugins(new File(pluginsPath, PLUGIN_LISTS_XML));
}
public void start() throws Exception{
for (IPluginModule plugin : plugins.values()) {
startPlugin(plugin);
}
}
private void startPlugin(IPluginModule plugin) {
IPluginActivator activator = plugin.getPluginActivator();
if (activator == null) {
return;
}
int state = activator.getState();
if (state == IPluginActivator.RUNNING || state == IPluginActivator.STARTING) { // 只要插件的状态不是RESOLVER,
return; // 则不能启动该插件,因为该插件可能正在停止或者正在启动过程中或者已经启动
}
try {
for (IPluginActuator actuator : startActuators) {
actuator.start(plugin);
}
} catch (RuntimeException e) {
logger.log(Level.SEVERE, "Initialize plugin actuator fail", e);
throw e;
}
}
private void stopPlugin(IPluginModule plugin) {
logger.info("stoping plugin:" + plugin.getPluginName());
IPluginActivator activator = plugin.getPluginActivator();
if (activator == null) {
return;
}
int state = activator.getState();
if (state == IPluginActivator.STOPPED || state == IPluginActivator.STOPPING) { // 只要插件的状态不是RESOLVER,
return; // 则不能启动该插件,因为该插件可能正在停止或者正在启动过程中或者已经启动
}
try {
for (IPluginActuator actuator : stopActuators) {
actuator.stop(plugin);
}
} catch (RuntimeException e) {
logger.log(Level.SEVERE, "stop plugin actuator fail", e);
throw e;
}
logger.info("stoped plugin:" + plugin.getPluginName());
}
public void reloadPlugin(String pluginName) throws Exception {
IPluginModule plugin = plugins.get(pluginName);
if(plugin != null) {
reloadPlugin(plugin);
}
}
private void reloadPlugin(IPluginModule plugin) throws Exception {
String pluginName = plugin.getPluginName();
logger.info("reload plugin " + pluginName);
if (plugins.get(pluginName) != null) {
unInstallPluin(pluginName);
startPlugin(loadPlugin(plugin.getPluginPath()));
}
}
public void destory() throws Exception {
for (IPluginModule plugin : getPlugins()) {
stopPlugin(plugin);
plugin.unload();
}
plugins.clear();
}
public void installPlugin(String folder) throws Exception {
IPluginModule plugin = loadPlugin(folder, null);
if (plugin != null) {
plugins.put(plugin.getPluginName(), plugin);
PluginContext.addPluginModule(plugin);
}
}
public void unInstallPluin(String pluginName) throws Exception {
IPluginModule plugin = plugins.get(pluginName);
//先停止插件,然后卸载插件
stopPlugin(plugin);
if(plugin != null) {
plugin.unload();
}
plugins.remove(pluginName);
}
private void installPlugins(File path) throws Exception {
XMLBuilder builder = XMLBuilder.createBuilder(path);
NodeList pluginNodes = builder.findNodeList(XML_PLUGIN);
for (int i = 0; i < pluginNodes.getLength(); i++) {
Node node = pluginNodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String folder = XMLBuilder.getAttribute(node, "folder");
String enable = XMLBuilder.getAttribute(node, "enable");
String filePath = XMLBuilder.getAttribute(node, "path");
if (Boolean.valueOf(enable)) {
IPluginModule plugin = loadPlugin(folder, filePath);
if(plugin != null) {
plugins.put(plugin.getPluginName(), plugin);
PluginContext.addPluginModule(plugin);
}
}
}
}
}
private IPluginModule loadPlugin(String folder, String filePath) {
if(StringUtil.isNullOrEmpty(filePath)) {
File pluginFolder = new File(pluginsPath, folder);
return loadPlugin(pluginFolder);
} else {
File pluginFolder = new File(filePath, folder);
return loadPlugin(pluginFolder);
}
}
private IPluginModule loadPlugin(File pluginFolder) {
logger.info("start load plugin:" + pluginFolder.getName());
if (pluginFolder.exists() && pluginFolder.isDirectory()) {
IPluginModule plugin = new PluginModule();
plugin.load(pluginFolder);
logger.info("plugin loaded:" + pluginFolder.getName());
return plugin;
} else {
logger.severe("plugin folder error:" + pluginFolder.getName());
return null;
}
}
public Collection<IPluginModule> getPlugins() {
return Collections.unmodifiableCollection(plugins.values());
}
public File getPluginsPath() {
return pluginsPath;
}
public void setPluginsPath(File pluginsPath) {
this.pluginsPath = pluginsPath;
}
}