From ae4cb7b21614e761600d814ffa9da06a7fc15f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=85=E8=8B=B1?= Date: Sun, 1 Apr 2018 14:32:59 +0800 Subject: [PATCH 01/24] 1.7.0.20180401 --- jarslink-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jarslink-api/pom.xml b/jarslink-api/pom.xml index 080ed61..2983c66 100644 --- a/jarslink-api/pom.xml +++ b/jarslink-api/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.alipay.jarslink jarslink-api - 1.6.1.20180301 + 1.7.0.20180401 Alipay JarsLink API https://github.com/alibaba/jarslink jar From 52e3ecf885e4a9771326ecdf08cffbc32e2f8d8a Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Sun, 1 Apr 2018 16:27:22 +0800 Subject: [PATCH 02/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E5=88=A0=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84?= =?UTF-8?q?=E5=BC=BA=E8=BD=AC=EF=BC=8C=E4=BC=98=E5=8C=96=E4=B8=80=E5=A4=84?= =?UTF-8?q?=E5=BE=AA=E7=8E=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jarslink/api/impl/ModuleManagerImpl.java | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java index 61f00f5..b1703c9 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java @@ -39,12 +39,10 @@ * * @author tengfei.fangtf * @version $Id: ModuleManagerImpl.java, v 0.1 Mar 20, 2017 4:04:32 PM tengfei.fangtf Exp $ - */ public class ModuleManagerImpl implements ModuleManager, DisposableBean { - private static final Logger LOGGER = LoggerFactory - .getLogger(ModuleManagerImpl.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ModuleManagerImpl.class); /** * 已注册的所有模块,key:moduleName upperCase @@ -60,15 +58,12 @@ private RuntimeModule getRuntimeModule(String name) { public List getModules() { List modules = Lists.newArrayList(); - for (String name : allModules.keySet()) { - RuntimeModule runtimeModule = getRuntimeModule((String) name); - for (String version : runtimeModule.getModules().keySet()) { - modules.add(runtimeModule.getModules().get(version)); - } + for (Map.Entry moduleEntry : allModules.entrySet()) { + RuntimeModule runtimeModule = moduleEntry.getValue(); + modules.addAll(runtimeModule.getModules().values()); } - return ImmutableList - .copyOf(filter(modules, instanceOf(SpringModule.class))); + return ImmutableList.copyOf(filter(modules, instanceOf(SpringModule.class))); } @Override @@ -79,20 +74,22 @@ public Module find(String name) { return find(name, defaultVersion); } - private String getDefaultVersion(String name) {return getRuntimeModule((String) name).getDefaultVersion();} + private String getDefaultVersion(String name) { + return getRuntimeModule(name).getDefaultVersion(); + } @Override public Module find(String name, String version) { checkNotNull(name, "module name is null"); checkNotNull(version, "module version is null"); - return getRuntimeModule((String) name).getModule(version); + return getRuntimeModule(name).getModule(version); } @Override public void activeVersion(String name, String version) { checkNotNull(name, "module name is null"); checkNotNull(version, "module version is null"); - getRuntimeModule((String) name).setDefaultVersion(version); + getRuntimeModule(name).setDefaultVersion(version); } @Override @@ -127,7 +124,7 @@ public Module register(Module module) { oldModule = runtimeModule.getDefaultModule(); runtimeModule.addModule(module).setDefaultVersion(version); // remove module old version - if (oldModule != null && module.getModuleConfig().isNeedUnloadOldVersion() && !runtimeModule.getModules().isEmpty()) { + if (oldModule != null && module.getModuleConfig().isNeedUnloadOldVersion()) { runtimeModule.getModules().remove(oldModule.getVersion()); } } @@ -141,14 +138,14 @@ public Module remove(String name) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Remove Module: {}", name); } - return remove(name, getRuntimeModule((String) name).getDefaultVersion()); + return remove(name, getRuntimeModule(name).getDefaultVersion()); } @Override public Module remove(String name, String version) { checkNotNull(name, "module name is null"); checkNotNull(version, "module version is null"); - return getRuntimeModule((String) name).getModules().remove(version); + return getRuntimeModule(name).getModules().remove(version); } @Override @@ -169,7 +166,7 @@ public Map getErrorModuleContext() { Map result = Maps.newHashMap(); for (String name : allModules.keySet()) { - RuntimeModule runtimeModule = getRuntimeModule((String) name); + RuntimeModule runtimeModule = getRuntimeModule(name); result.put(name, runtimeModule.getErrorContext()); } From 227b4f28bce531a59e43764fa509056dbf965a10 Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Sun, 1 Apr 2018 17:40:50 +0800 Subject: [PATCH 03/24] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E5=B9=B6=E5=8F=91?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alipay/jarslink/api/ModuleManager.java | 12 +- .../jarslink/api/impl/ModuleManagerImpl.java | 188 +++++++++++++----- 2 files changed, 146 insertions(+), 54 deletions(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleManager.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleManager.java index 4d8aa24..07e767d 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleManager.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleManager.java @@ -38,7 +38,8 @@ public interface ModuleManager { /** * 根据模块名和版本查找Module - * @param name 模块名称 + * + * @param name 模块名称 * @param version 模块版本号 * @return */ @@ -68,12 +69,13 @@ public interface ModuleManager { List getModules(); /** - * 注册一个Module + * 注册一个Module,同时该module将会被设置为默认module * * @param module 模块 * @return 旧模块, 如果没有旧模块则返回null + * @throws ModuleRuntimeException 如果当前系统中存在该模块那么将会抛出该异常 */ - Module register(Module module); + Module register(Module module) throws ModuleRuntimeException; /** * 移除已激活版本的Module @@ -86,8 +88,8 @@ public interface ModuleManager { /** * 移除一个Module * - * @param name 模块名 - * @param version 版本号 + * @param name 模块名 + * @param version 版本号 * @return 被移除的模块 */ Module remove(String name, String version); diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java index b1703c9..84dd027 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java @@ -19,6 +19,7 @@ import com.alipay.jarslink.api.Module; import com.alipay.jarslink.api.ModuleManager; +import com.alipay.jarslink.api.ModuleRuntimeException; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -26,9 +27,12 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Callable; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Predicates.instanceOf; @@ -46,32 +50,48 @@ public class ModuleManagerImpl implements ModuleManager, DisposableBean { /** * 已注册的所有模块,key:moduleName upperCase + *

+ * 使用HashMap替换ConcurrentHashMap,内部使用ReentrantReadWriteLock控制并发逻辑 */ - private final ConcurrentHashMap allModules = new ConcurrentHashMap(); + private final Map allModules = new HashMap(); + /** + * 操作allModules的资源锁 + */ + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private RuntimeModule getRuntimeModule(String name) { - RuntimeModule runtimeModule = allModules.get(name.toUpperCase()); - return runtimeModule != null ? runtimeModule : new RuntimeModule(); + return readExec(new Callable() { + @Override + public RuntimeModule call() { + RuntimeModule runtimeModule = allModules.get(name.toUpperCase()); + return runtimeModule != null ? runtimeModule : new RuntimeModule(); + } + }); } @Override public List getModules() { - List modules = Lists.newArrayList(); - - for (Map.Entry moduleEntry : allModules.entrySet()) { - RuntimeModule runtimeModule = moduleEntry.getValue(); - modules.addAll(runtimeModule.getModules().values()); - } - + final List modules = Lists.newArrayList(); + readExec(new Callable() { + @Override + public Integer call() { + for (Map.Entry moduleEntry : allModules.entrySet()) { + RuntimeModule runtimeModule = moduleEntry.getValue(); + modules.addAll(runtimeModule.getModules().values()); + } + return null; + } + }); return ImmutableList.copyOf(filter(modules, instanceOf(SpringModule.class))); } @Override public Module find(String name) { checkNotNull(name, "module name is null"); - String defaultVersion = getDefaultVersion(name); + RuntimeModule runtimeModule = getRuntimeModule(name); + String defaultVersion = runtimeModule.getDefaultVersion(); checkNotNull(defaultVersion, "module default version is null"); - return find(name, defaultVersion); + return runtimeModule.getModule(defaultVersion); } private String getDefaultVersion(String name) { @@ -101,37 +121,42 @@ public String getActiveVersion(String name) { @Override public Module register(Module module) { checkNotNull(module, "module is null"); - String name = module.getName(); - String version = module.getVersion(); + final String name = module.getName(); + final String version = module.getVersion(); if (LOGGER.isInfoEnabled()) { LOGGER.info("register Module: {}-{}", name, version); } - //same module and same version can not register - Module registeredModule = getRuntimeModule(name).getModule(version); - if (registeredModule != null) { - return null; - } + //此处如果不加读锁,那么多线程情况下有可能同时进入runtimeModule.getModules().isEmpty(),此时多个线程 + //将同时调用allModules.put(name.toUpperCase(), runtimeModule),而由于key相同,此时只有一个线程会成功,而 + //失败的线程也无法得知自己已经失败 + return writeExec(new Callable() { + @Override + public Module call() { + //如果当前系统存在该模块那么应该抛出异常,否则外部调用无法得知是否注册成功 + ModuleManagerImpl.this.checkDuplicate(name, version); - RuntimeModule runtimeModule = getRuntimeModule(name); - Module oldModule = null; - //module frist register - if (runtimeModule.getModules().isEmpty()) { - runtimeModule = new RuntimeModule().withName(name).withDefaultVersion(version).addModule(module); - allModules.put(name.toUpperCase(), runtimeModule); - } else { - //the same module to register again - oldModule = runtimeModule.getDefaultModule(); - runtimeModule.addModule(module).setDefaultVersion(version); - // remove module old version - if (oldModule != null && module.getModuleConfig().isNeedUnloadOldVersion()) { - runtimeModule.getModules().remove(oldModule.getVersion()); + RuntimeModule runtimeModule = getRuntimeModule(name); + Module oldModule = null; + //module frist register + if (runtimeModule.getModules().isEmpty()) { + runtimeModule = new RuntimeModule().withName(name).withDefaultVersion(version).addModule(module); + allModules.put(name.toUpperCase(), runtimeModule); + } else { + //the same module to register again + oldModule = runtimeModule.getDefaultModule(); + runtimeModule.addModule(module).setDefaultVersion(version); + // remove module old version + if (oldModule != null && module.getModuleConfig().isNeedUnloadOldVersion()) { + runtimeModule.getModules().remove(oldModule.getVersion()); + } + } + return oldModule; } - } - - return oldModule; + }); } + @Override public Module remove(String name) { checkNotNull(name, "module name is null"); @@ -150,27 +175,92 @@ public Module remove(String name, String version) { @Override public void destroy() throws Exception { - for (Module each : getModules()) { - try { - each.destroy(); - } catch (Exception e) { - LOGGER.error("Failed to destroy module: " + each.getName(), e); + writeExec(new Callable() { + @Override + public Object call() { + for (Module each : getModules()) { + try { + each.destroy(); + } catch (Exception e) { + LOGGER.error("Failed to destroy module: " + each.getName(), e); + } + } + + allModules.clear(); + return null; } - } - allModules.clear(); + }); } @Override public Map getErrorModuleContext() { + return readExec(new Callable>() { + @Override + public Map call() { + final Map result = Maps.newHashMap(); + for (String name : allModules.keySet()) { + RuntimeModule runtimeModule = getRuntimeModule(name); + result.put(name, runtimeModule.getErrorContext()); + } + return result; + } + }); + } - Map result = Maps.newHashMap(); - - for (String name : allModules.keySet()) { - RuntimeModule runtimeModule = getRuntimeModule(name); - result.put(name, runtimeModule.getErrorContext()); + /** + * 检查当前是否有指定模块的指定版本存在系统 + * + * @param name 模块名 + * @param version 版本号 + * @throws ModuleRuntimeException 如果当前系统存在该模块的指定版本将抛出异常 + */ + private void checkDuplicate(String name, String version) throws ModuleRuntimeException { + RuntimeModule runtimeModule = allModules.get(name.toUpperCase()); + runtimeModule = runtimeModule != null ? runtimeModule : new RuntimeModule(); + Module registeredModule = runtimeModule.getModule(version); + if (registeredModule != null) { + StringBuilder sb = new StringBuilder(); + sb.append("duplicate module :[").append(name).append(":").append(version).append("]"); + throw new ModuleRuntimeException(sb.toString()); } + } - return result; + + /** + * 对allModules的读操作 + * + * @param operation 操作 + * @param 操作返回值类型 + * @return 操作结果 + */ + private T readExec(Callable operation) { + Lock readlock = lock.readLock(); + readlock.lock(); + try { + return operation.call(); + } catch (Exception e) { + throw new ModuleRuntimeException("readExec error", e); + } finally { + readlock.unlock(); + } } + /** + * 对allModules的写操作 + * + * @param operation 操作 + * @param 操作返回值类型 + * @return 操作结果 + */ + private T writeExec(Callable operation) { + Lock writeLock = lock.writeLock(); + writeLock.lock(); + try { + return operation.call(); + } catch (Exception e) { + throw new ModuleRuntimeException("writeExec error", e); + } finally { + writeLock.unlock(); + } + } } \ No newline at end of file From 20b8d6a00bbe73797197a80e68ad050da85c1c76 Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Sun, 1 Apr 2018 18:01:13 +0800 Subject: [PATCH 04/24] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=88=E7=94=B1=E4=BA=8E=E6=9B=B4=E6=94=B9?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E9=80=BB=E8=BE=91=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=EF=BC=8C=E4=B8=BB=E8=A6=81=E6=98=AF=E7=94=B1=E4=BA=8EModuleMan?= =?UTF-8?q?ager=E6=8E=A5=E5=8F=A3=E7=9A=84register=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E9=80=A0=E6=88=90=E7=9A=84=EF=BC=8C=E5=8E=9F=E6=9D=A5=E5=BD=93?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E9=87=8D=E5=A4=8D=E6=A8=A1=E5=9D=97=E6=97=B6?= =?UTF-8?q?=E4=BC=9A=E8=BF=94=E5=9B=9Enull=EF=BC=8C=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E4=BC=9A=E6=8A=9B=E5=87=BA=E5=BC=82=E5=B8=B8=EF=BC=8C=E6=9D=A5?= =?UTF-8?q?=E8=B7=9F=E5=8F=A6=E4=B8=80=E7=A7=8D=E6=83=85=E5=86=B5=20[=20?= =?UTF-8?q?=E5=BD=93=E4=B8=8D=E5=AD=98=E5=9C=A8=E6=97=A7=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E6=97=B6=E8=BF=94=E5=9B=9Enull=20]=20=E5=8C=BA=E5=88=86?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/impl/ModuleLoaderImplTest.java | 22 +++++++++---------- .../jarslink/api/impl/ModuleManagerTest.java | 10 +++++++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleLoaderImplTest.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleLoaderImplTest.java index 4f59472..a3e2f71 100644 --- a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleLoaderImplTest.java +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleLoaderImplTest.java @@ -21,7 +21,6 @@ import java.util.Map; /** - * * @author tengfei.fang * @version $Id: ModuleLoaderImplTest.java, v 0.1 2018年04月01日 12:12 PM tengfei.fang Exp $ */ @@ -37,9 +36,10 @@ public class ModuleLoaderImplTest { @Test public void shouldLoadModule() { //1:加载模块 - Module module = loadModule(); + String version = Double.toString(Math.random()); + Module module = loadModuleWithVersion(version); Assert.assertEquals("demo", module.getName()); - Assert.assertEquals("1.0.0.20170621", module.getVersion()); + Assert.assertEquals(version, module.getVersion()); Assert.assertEquals(3, module.getActions().size()); Assert.assertNotNull(module); Assert.assertNotNull(module.getCreation()); @@ -68,7 +68,7 @@ public void shouldLoadMultiModule() { @Test public void shouldDoAction() { - Module module = loadModule(); + Module module = loadModuleWithVersion(Double.toString(Math.random())); String actionName = "helloworld"; //4.1:查找和执行Action @@ -193,11 +193,11 @@ public static ModuleConfig buildModuleConfig() { } public static ModuleConfig buildModuleConfig(boolean enabled) { - return buildModuleConfig("demo", "1.0.0.20170621", enabled); + return buildModuleConfig("demo", Double.toString(Math.random()), enabled); } public static ModuleConfig buildModuleConfig(String name, boolean enabled) { - return buildModuleConfig(name, "1.0.0.20170621", enabled); + return buildModuleConfig(name, Double.toString(Math.random()), enabled); } public static ModuleConfig buildModuleConfig(String name, String version, boolean enabled) { @@ -208,23 +208,23 @@ public static ModuleConfig buildModuleConfig(String name, String version, boolea moduleConfig.addScanPackage(scanBase); moduleConfig.removeScanPackage(scanBase); Map properties = new HashMap(); - moduleConfig.withEnabled(enabled).withVersion("1.0.0.20170621").withOverridePackages(ImmutableList.of( - "com.alipay.jarslink.demo")).withProperties(properties); + moduleConfig.withEnabled(enabled).withVersion(version).withOverridePackages(ImmutableList.of("com.alipay" + "" + + ".jarslink.demo")).withProperties(properties); demoModule = Thread.currentThread().getContextClassLoader().getResource(JARSLINK_MODULE_DEMO); moduleConfig.setOverridePackages(ImmutableList.of("com.alipay.jarslink.demo")); moduleConfig.setName(name); moduleConfig.setEnabled(enabled); - moduleConfig.setVersion("1.0.0.20170621"); + moduleConfig.setVersion(version); properties.put("url", "127.0.0.1"); moduleConfig.setProperties(properties); moduleConfig.setModuleUrl(ImmutableList.of(demoModule)); return moduleConfig; } - private Module loadModule() { - return moduleLoader.load(buildModuleConfig(true)); + private Module loadModuleWithVersion(String version) { + return moduleLoader.load(buildModuleConfig("demo", version, true)); } private Module loadModule(String name) { diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleManagerTest.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleManagerTest.java index de4d7ea..b88d9ea 100644 --- a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleManagerTest.java +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleManagerTest.java @@ -20,6 +20,7 @@ import com.alipay.jarslink.api.Module; import com.alipay.jarslink.api.ModuleLoader; import com.alipay.jarslink.api.ModuleManager; +import com.alipay.jarslink.api.ModuleRuntimeException; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -84,8 +85,13 @@ public void shouldNotRegisterSameVersionModule() { Assert.assertNull(removedModule); Assert.assertEquals(1, moduleManager.getModules().size()); - //再注册同一个模块,不会注册成功,返回空 - Module register = moduleManager.register(module); + //再注册同一个模块,将会抛出异常 + Module register = null; + try { + register = moduleManager.register(module); + } catch (ModuleRuntimeException e) { + Assert.assertNotNull(e); + } Assert.assertNull(register); Assert.assertEquals(1, moduleManager.getModules().size()); } From 7c575d05f5b0c7f4ec582252b2022e5eb775a5d3 Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Sun, 1 Apr 2018 23:32:29 +0800 Subject: [PATCH 05/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B9=B6=E5=8F=91BUG?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/impl/ConcurrentModuleManagerImpl.java | 179 ++++++++++++++++++ .../impl/ConcurrentModuleManagerImplTest.java | 103 ++++++++++ .../resources/META-INF/spring/jarslink.xml | 5 +- 3 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImpl.java create mode 100644 jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImpl.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImpl.java new file mode 100644 index 0000000..3a5b902 --- /dev/null +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImpl.java @@ -0,0 +1,179 @@ +package com.alipay.jarslink.api.impl; + +import com.alipay.jarslink.api.Module; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.instanceOf; +import static com.google.common.collect.Iterables.filter; + +/** + * @author joe + * @version 2018.04.01 22:54 + */ +@Component("testModuleManager") +public class ConcurrentModuleManagerImpl extends ModuleManagerImpl { + + private CountDownLatch countDownLatch = null; + private static final Logger LOGGER = LoggerFactory.getLogger(ModuleManagerImpl.class); + + public void activeConcurrentTest() { + countDownLatch = new CountDownLatch(2); + } + + public void disableConcurrentTest() { + countDownLatch = null; + } + + /** + * 已注册的所有模块,key:moduleName upperCase + */ + private final ConcurrentHashMap allModules = new ConcurrentHashMap(); + + private RuntimeModule getRuntimeModule(String name) { + RuntimeModule runtimeModule = allModules.get(name.toUpperCase()); + return runtimeModule != null ? runtimeModule : new RuntimeModule(); + } + + @Override + public List getModules() { + List modules = Lists.newArrayList(); + + for (String name : allModules.keySet()) { + RuntimeModule runtimeModule = getRuntimeModule((String) name); + for (String version : runtimeModule.getModules().keySet()) { + modules.add(runtimeModule.getModules().get(version)); + } + } + + return ImmutableList.copyOf(filter(modules, instanceOf(SpringModule.class))); + } + + @Override + public Module find(String name) { + checkNotNull(name, "module name is null"); + String defaultVersion = getDefaultVersion(name); + checkNotNull(defaultVersion, "module default version is null"); + return find(name, defaultVersion); + } + + private String getDefaultVersion(String name) { + return getRuntimeModule((String) name).getDefaultVersion(); + } + + @Override + public Module find(String name, String version) { + checkNotNull(name, "module name is null"); + checkNotNull(version, "module version is null"); + return getRuntimeModule((String) name).getModule(version); + } + + @Override + public void activeVersion(String name, String version) { + checkNotNull(name, "module name is null"); + checkNotNull(version, "module version is null"); + getRuntimeModule((String) name).setDefaultVersion(version); + } + + @Override + public String getActiveVersion(String name) { + checkNotNull(name, "module name is null"); + return getDefaultVersion(name); + } + + @Override + public Module register(Module module) { + checkNotNull(module, "module is null"); + String name = module.getName(); + String version = module.getVersion(); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("register Module: {}-{}", name, version); + } + + //same module and same version can not register + Module registeredModule = getRuntimeModule(name).getModule(version); + if (registeredModule != null) { + return null; + } + + RuntimeModule runtimeModule = getRuntimeModule(name); + Module oldModule = null; + if (countDownLatch != null) { + countDownLatch.countDown(); + try { + countDownLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + //module frist register + if (runtimeModule.getModules().isEmpty()) { + runtimeModule = new RuntimeModule().withName(name).withDefaultVersion(version).addModule(module); + allModules.put(name.toUpperCase(), runtimeModule); + } else { + //the same module to register again + oldModule = runtimeModule.getDefaultModule(); + runtimeModule.addModule(module).setDefaultVersion(version); + // remove module old version + if (oldModule != null && module.getModuleConfig().isNeedUnloadOldVersion() && !runtimeModule.getModules() + .isEmpty()) { + runtimeModule.getModules().remove(oldModule.getVersion()); + } + } + + return oldModule; + } + + @Override + public Module remove(String name) { + checkNotNull(name, "module name is null"); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Remove Module: {}", name); + } + return remove(name, getRuntimeModule((String) name).getDefaultVersion()); + } + + @Override + public Module remove(String name, String version) { + checkNotNull(name, "module name is null"); + checkNotNull(version, "module version is null"); + return getRuntimeModule((String) name).getModules().remove(version); + } + + @Override + public void destroy() throws Exception { + for (Module each : getModules()) { + try { + each.destroy(); + } catch (Exception e) { + LOGGER.error("Failed to destroy module: " + each.getName(), e); + } + } + allModules.clear(); + } + + @Override + public Map getErrorModuleContext() { + + Map result = Maps.newHashMap(); + + for (String name : allModules.keySet()) { + RuntimeModule runtimeModule = getRuntimeModule((String) name); + result.put(name, runtimeModule.getErrorContext()); + } + + return result; + } + + +} diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java new file mode 100644 index 0000000..9b48073 --- /dev/null +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java @@ -0,0 +1,103 @@ +package com.alipay.jarslink.api.impl; + +import com.alipay.jarslink.api.Module; +import com.alipay.jarslink.api.ModuleConfig; +import com.alipay.jarslink.api.ModuleLoader; +import com.google.common.collect.ImmutableList; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +/** + * @author joe + * @version 2018.04.01 22:58 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath*:META-INF/spring/jarslink.xml"}) +public class ConcurrentModuleManagerImplTest { + public static final String JARSLINK_MODULE_DEMO = "jarslink-module-demo-1.0.0.jar"; + @Autowired + private ConcurrentModuleManagerImpl testModuleManager; + @Autowired + private ModuleLoader moduleLoader; + + + @Test + public void concurrentTest() { + testModuleManager.activeConcurrentTest(); + + Module m1 = moduleLoader.load(buildModuleConfig("1.0").withNeedUnloadOldVersion(false)); + Module m2 = moduleLoader.load(buildModuleConfig("2.0").withNeedUnloadOldVersion(false)); + + + Thread t1 = new Thread(new Runnable() { + @Override + public void run() { + testModuleManager.register(m1); + } + }); + + Thread t2 = new Thread(new Runnable() { + @Override + public void run() { + testModuleManager.register(m2); + } + }); + + t1.start(); + t2.start(); + + try { + t1.join(); + t2.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Module m3 = testModuleManager.find("demo", "1.0"); + Module m4 = testModuleManager.find("demo", "2.0"); + + //由于存在并发BUG,所以此处两个肯定有一个是null + Assert.assertTrue((m3 == null && m4 != null) || (m3 != null && m4 == null)); + + testModuleManager.disableConcurrentTest(); + } + + @Test + public void noConcurrentTest() { + Module m1 = moduleLoader.load(buildModuleConfig("1.0").withNeedUnloadOldVersion(false)); + Module m2 = moduleLoader.load(buildModuleConfig("2.0").withNeedUnloadOldVersion(false)); + testModuleManager.register(m1); + testModuleManager.register(m2); + + m1 = testModuleManager.find("demo", "1.0"); + m2 = testModuleManager.find("demo", "2.0"); + + //没有并发是表现正常,两个都能注册成功 + Assert.assertTrue(m1 != null && m2 != null); + } + + private ModuleConfig buildModuleConfig(String version) { + URL demoModule; + ModuleConfig moduleConfig = new ModuleConfig(); + //通过该方法构建的配置都是使用注解形式扫描bean的 + String scanBase = "com.alipay.jarslink.main"; + moduleConfig.addScanPackage(scanBase); + moduleConfig.removeScanPackage(scanBase); + Map properties = new HashMap(); + properties.put("url", "127.0.0.1"); + moduleConfig.withEnabled(true).withVersion(version).withOverridePackages(ImmutableList.of("com.alipay" + "" + + ".jarslink.demo")).withName("demo").withProperties(properties); + demoModule = Thread.currentThread().getContextClassLoader().getResource(JARSLINK_MODULE_DEMO); + moduleConfig.setModuleUrl(ImmutableList.of(demoModule)); + return moduleConfig; + } + +} diff --git a/jarslink-api/src/test/resources/META-INF/spring/jarslink.xml b/jarslink-api/src/test/resources/META-INF/spring/jarslink.xml index dbe7c8e..fd759f8 100644 --- a/jarslink-api/src/test/resources/META-INF/spring/jarslink.xml +++ b/jarslink-api/src/test/resources/META-INF/spring/jarslink.xml @@ -1,7 +1,8 @@ + + From 838468a5b8c9d67224cff88b4989c475dd60c88b Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Mon, 2 Apr 2018 00:37:26 +0800 Subject: [PATCH 06/24] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E5=B9=B6=E5=8F=91BUG?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/ConcurrentModuleManagerImplTest.java | 35 +++---------------- .../jarslink/api/impl/RegisterTask.java | 22 ++++++++++++ 2 files changed, 27 insertions(+), 30 deletions(-) create mode 100644 jarslink-api/src/test/java/com/alipay/jarslink/api/impl/RegisterTask.java diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java index 9b48073..e0f0633 100644 --- a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java @@ -37,19 +37,8 @@ public void concurrentTest() { Module m2 = moduleLoader.load(buildModuleConfig("2.0").withNeedUnloadOldVersion(false)); - Thread t1 = new Thread(new Runnable() { - @Override - public void run() { - testModuleManager.register(m1); - } - }); - - Thread t2 = new Thread(new Runnable() { - @Override - public void run() { - testModuleManager.register(m2); - } - }); + Thread t1 = new Thread(new RegisterTask(testModuleManager, m1)); + Thread t2 = new Thread(new RegisterTask(testModuleManager, m2)); t1.start(); t2.start(); @@ -61,29 +50,15 @@ public void run() { e.printStackTrace(); } - Module m3 = testModuleManager.find("demo", "1.0"); - Module m4 = testModuleManager.find("demo", "2.0"); + m1 = testModuleManager.find("demo", "1.0"); + m2 = testModuleManager.find("demo", "2.0"); //由于存在并发BUG,所以此处两个肯定有一个是null - Assert.assertTrue((m3 == null && m4 != null) || (m3 != null && m4 == null)); + Assert.assertTrue((m1 == null && m2 != null) || (m1 != null && m2 == null)); testModuleManager.disableConcurrentTest(); } - @Test - public void noConcurrentTest() { - Module m1 = moduleLoader.load(buildModuleConfig("1.0").withNeedUnloadOldVersion(false)); - Module m2 = moduleLoader.load(buildModuleConfig("2.0").withNeedUnloadOldVersion(false)); - testModuleManager.register(m1); - testModuleManager.register(m2); - - m1 = testModuleManager.find("demo", "1.0"); - m2 = testModuleManager.find("demo", "2.0"); - - //没有并发是表现正常,两个都能注册成功 - Assert.assertTrue(m1 != null && m2 != null); - } - private ModuleConfig buildModuleConfig(String version) { URL demoModule; ModuleConfig moduleConfig = new ModuleConfig(); diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/RegisterTask.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/RegisterTask.java new file mode 100644 index 0000000..4dc85f1 --- /dev/null +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/RegisterTask.java @@ -0,0 +1,22 @@ +package com.alipay.jarslink.api.impl; + +import com.alipay.jarslink.api.Module; + +/** + * @author joe + * @version 2018.04.02 00:15 + */ +public class RegisterTask implements Runnable { + private ConcurrentModuleManagerImpl concurrentModuleManager; + private Module m1; + + public RegisterTask(ConcurrentModuleManagerImpl concurrentModuleManager, Module m1) { + this.concurrentModuleManager = concurrentModuleManager; + this.m1 = m1; + } + + @Override + public void run() { + concurrentModuleManager.register(m1); + } +} From 17db41f38a956c5ba54f53b192558cf375a40f29 Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Mon, 2 Apr 2018 11:25:40 +0800 Subject: [PATCH 07/24] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=EF=BC=8C=E5=88=A0=E9=99=A4=E6=8A=9B=E5=87=BA?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/alipay/jarslink/api/ModuleManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleManager.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleManager.java index 07e767d..249019f 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleManager.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleManager.java @@ -73,9 +73,10 @@ public interface ModuleManager { * * @param module 模块 * @return 旧模块, 如果没有旧模块则返回null - * @throws ModuleRuntimeException 如果当前系统中存在该模块那么将会抛出该异常 + *

+ * 如果当前系统中已经存在该模块那么将会抛出该异常 */ - Module register(Module module) throws ModuleRuntimeException; + Module register(Module module); /** * 移除已激活版本的Module From 68a73574dd3cf4f01b323266821fdb12a57143ff Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Mon, 2 Apr 2018 22:56:33 +0800 Subject: [PATCH 08/24] =?UTF-8?q?=E6=9B=B4=E6=94=B9Map=E4=B8=BAConcurrentM?= =?UTF-8?q?ap=EF=BC=8C=E8=AF=BB=E6=93=8D=E4=BD=9C=E4=B8=8D=E5=8A=A0?= =?UTF-8?q?=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jarslink/api/impl/ModuleManagerImpl.java | 63 +++++-------------- 1 file changed, 14 insertions(+), 49 deletions(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java index 84dd027..7e22ea5 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -53,35 +54,24 @@ public class ModuleManagerImpl implements ModuleManager, DisposableBean { *

* 使用HashMap替换ConcurrentHashMap,内部使用ReentrantReadWriteLock控制并发逻辑 */ - private final Map allModules = new HashMap(); + private final Map allModules = new ConcurrentHashMap(); /** * 操作allModules的资源锁 */ private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private RuntimeModule getRuntimeModule(String name) { - return readExec(new Callable() { - @Override - public RuntimeModule call() { - RuntimeModule runtimeModule = allModules.get(name.toUpperCase()); - return runtimeModule != null ? runtimeModule : new RuntimeModule(); - } - }); + RuntimeModule runtimeModule = allModules.get(name.toUpperCase()); + return runtimeModule != null ? runtimeModule : new RuntimeModule(); } @Override public List getModules() { final List modules = Lists.newArrayList(); - readExec(new Callable() { - @Override - public Integer call() { - for (Map.Entry moduleEntry : allModules.entrySet()) { - RuntimeModule runtimeModule = moduleEntry.getValue(); - modules.addAll(runtimeModule.getModules().values()); - } - return null; - } - }); + for (Map.Entry moduleEntry : allModules.entrySet()) { + RuntimeModule runtimeModule = moduleEntry.getValue(); + modules.addAll(runtimeModule.getModules().values()); + } return ImmutableList.copyOf(filter(modules, instanceOf(SpringModule.class))); } @@ -194,17 +184,12 @@ public Object call() { @Override public Map getErrorModuleContext() { - return readExec(new Callable>() { - @Override - public Map call() { - final Map result = Maps.newHashMap(); - for (String name : allModules.keySet()) { - RuntimeModule runtimeModule = getRuntimeModule(name); - result.put(name, runtimeModule.getErrorContext()); - } - return result; - } - }); + final Map result = Maps.newHashMap(); + for (String name : allModules.keySet()) { + RuntimeModule runtimeModule = getRuntimeModule(name); + result.put(name, runtimeModule.getErrorContext()); + } + return result; } /** @@ -225,26 +210,6 @@ private void checkDuplicate(String name, String version) throws ModuleRuntimeExc } } - - /** - * 对allModules的读操作 - * - * @param operation 操作 - * @param 操作返回值类型 - * @return 操作结果 - */ - private T readExec(Callable operation) { - Lock readlock = lock.readLock(); - readlock.lock(); - try { - return operation.call(); - } catch (Exception e) { - throw new ModuleRuntimeException("readExec error", e); - } finally { - readlock.unlock(); - } - } - /** * 对allModules的写操作 * From af1ff428bccc540d40f27363ce31b4d80b168c28 Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Mon, 2 Apr 2018 22:56:46 +0800 Subject: [PATCH 09/24] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E5=AF=BC=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java index 7e22ea5..111d033 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java @@ -27,7 +27,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; From a7f22219fcc419814a4472b56f0f87a46ad46a33 Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Mon, 2 Apr 2018 22:58:03 +0800 Subject: [PATCH 10/24] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jarslink/api/impl/ConcurrentModuleManagerImplTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java index e0f0633..55a01f8 100644 --- a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ConcurrentModuleManagerImplTest.java @@ -47,7 +47,8 @@ public void concurrentTest() { t1.join(); t2.join(); } catch (InterruptedException e) { - e.printStackTrace(); + //此处不会抛出异常 + Assert.assertNull(e); } m1 = testModuleManager.find("demo", "1.0"); From 23cda22b806ed6022014aac089f465772a24e524 Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Mon, 2 Apr 2018 23:16:14 +0800 Subject: [PATCH 11/24] =?UTF-8?q?=E4=BD=BF=E7=94=A8synchronize=E4=BB=A3?= =?UTF-8?q?=E6=9B=BFlock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jarslink/api/impl/ModuleManagerImpl.java | 93 ++++++------------- 1 file changed, 27 insertions(+), 66 deletions(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java index 111d033..ef20ea3 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java @@ -29,10 +29,7 @@ import java.util.List; import java.util.Map; -import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Predicates.instanceOf; @@ -50,14 +47,8 @@ public class ModuleManagerImpl implements ModuleManager, DisposableBean { /** * 已注册的所有模块,key:moduleName upperCase - *

- * 使用HashMap替换ConcurrentHashMap,内部使用ReentrantReadWriteLock控制并发逻辑 */ private final Map allModules = new ConcurrentHashMap(); - /** - * 操作allModules的资源锁 - */ - private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private RuntimeModule getRuntimeModule(String name) { RuntimeModule runtimeModule = allModules.get(name.toUpperCase()); @@ -108,7 +99,7 @@ public String getActiveVersion(String name) { } @Override - public Module register(Module module) { + public synchronized Module register(Module module) { checkNotNull(module, "module is null"); final String name = module.getName(); final String version = module.getVersion(); @@ -119,30 +110,25 @@ public Module register(Module module) { //此处如果不加读锁,那么多线程情况下有可能同时进入runtimeModule.getModules().isEmpty(),此时多个线程 //将同时调用allModules.put(name.toUpperCase(), runtimeModule),而由于key相同,此时只有一个线程会成功,而 //失败的线程也无法得知自己已经失败 - return writeExec(new Callable() { - @Override - public Module call() { - //如果当前系统存在该模块那么应该抛出异常,否则外部调用无法得知是否注册成功 - ModuleManagerImpl.this.checkDuplicate(name, version); - - RuntimeModule runtimeModule = getRuntimeModule(name); - Module oldModule = null; - //module frist register - if (runtimeModule.getModules().isEmpty()) { - runtimeModule = new RuntimeModule().withName(name).withDefaultVersion(version).addModule(module); - allModules.put(name.toUpperCase(), runtimeModule); - } else { - //the same module to register again - oldModule = runtimeModule.getDefaultModule(); - runtimeModule.addModule(module).setDefaultVersion(version); - // remove module old version - if (oldModule != null && module.getModuleConfig().isNeedUnloadOldVersion()) { - runtimeModule.getModules().remove(oldModule.getVersion()); - } - } - return oldModule; + //如果当前系统存在该模块那么应该抛出异常,否则外部调用无法得知是否注册成功 + checkDuplicate(name, version); + + RuntimeModule runtimeModule = getRuntimeModule(name); + Module oldModule = null; + //module frist register + if (runtimeModule.getModules().isEmpty()) { + runtimeModule = new RuntimeModule().withName(name).withDefaultVersion(version).addModule(module); + allModules.put(name.toUpperCase(), runtimeModule); + } else { + //the same module to register again + oldModule = runtimeModule.getDefaultModule(); + runtimeModule.addModule(module).setDefaultVersion(version); + // remove module old version + if (oldModule != null && module.getModuleConfig().isNeedUnloadOldVersion()) { + runtimeModule.getModules().remove(oldModule.getVersion()); } - }); + } + return oldModule; } @@ -164,21 +150,15 @@ public Module remove(String name, String version) { @Override public void destroy() throws Exception { - writeExec(new Callable() { - @Override - public Object call() { - for (Module each : getModules()) { - try { - each.destroy(); - } catch (Exception e) { - LOGGER.error("Failed to destroy module: " + each.getName(), e); - } - } - - allModules.clear(); - return null; + for (Module each : getModules()) { + try { + each.destroy(); + } catch (Exception e) { + LOGGER.error("Failed to destroy module: " + each.getName(), e); } - }); + } + + allModules.clear(); } @Override @@ -208,23 +188,4 @@ private void checkDuplicate(String name, String version) throws ModuleRuntimeExc throw new ModuleRuntimeException(sb.toString()); } } - - /** - * 对allModules的写操作 - * - * @param operation 操作 - * @param 操作返回值类型 - * @return 操作结果 - */ - private T writeExec(Callable operation) { - Lock writeLock = lock.writeLock(); - writeLock.lock(); - try { - return operation.call(); - } catch (Exception e) { - throw new ModuleRuntimeException("writeExec error", e); - } finally { - writeLock.unlock(); - } - } } \ No newline at end of file From 26400dd5f674b52b85902a4d019945af4bd48919 Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Mon, 2 Apr 2018 23:23:17 +0800 Subject: [PATCH 12/24] =?UTF-8?q?=E6=9B=B4=E6=94=B9StringBuilder=E4=B8=BA?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E4=BD=BF=E7=94=A8+=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java index ef20ea3..2f9db43 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleManagerImpl.java @@ -183,9 +183,7 @@ private void checkDuplicate(String name, String version) throws ModuleRuntimeExc runtimeModule = runtimeModule != null ? runtimeModule : new RuntimeModule(); Module registeredModule = runtimeModule.getModule(version); if (registeredModule != null) { - StringBuilder sb = new StringBuilder(); - sb.append("duplicate module :[").append(name).append(":").append(version).append("]"); - throw new ModuleRuntimeException(sb.toString()); + throw new ModuleRuntimeException("duplicate module :[" + name + ":" + version + "]"); } } } \ No newline at end of file From 6e3065a1ac29233c0a18f9e66f1f2390f4dfc8a0 Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Tue, 3 Apr 2018 19:50:39 +0800 Subject: [PATCH 13/24] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BE=9D=E8=B5=96spring-aop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jarslink-api/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/jarslink-api/pom.xml b/jarslink-api/pom.xml index 2983c66..fb890e1 100644 --- a/jarslink-api/pom.xml +++ b/jarslink-api/pom.xml @@ -51,11 +51,6 @@ - - org.springframework - spring-aop - ${org.springframework.version} - org.springframework spring-context From 091411efe4b56f17b817f5d5326267965507cf42 Mon Sep 17 00:00:00 2001 From: JoeKerouac <1213812243@qq.com> Date: Tue, 3 Apr 2018 19:55:05 +0800 Subject: [PATCH 14/24] =?UTF-8?q?=E5=88=A0=E9=99=A4common-logging=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=EF=BC=88=E5=8F=AA=E4=BF=9D=E7=95=99slf4j=EF=BC=8C?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=94=B1=E7=94=A8=E6=88=B7=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E6=8F=90=E4=BE=9B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jarslink-api/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/jarslink-api/pom.xml b/jarslink-api/pom.xml index fb890e1..d28d5b1 100644 --- a/jarslink-api/pom.xml +++ b/jarslink-api/pom.xml @@ -57,11 +57,6 @@ ${org.springframework.version} true - - commons-logging - commons-logging - 1.1.3 - org.apache.commons commons-lang3 From 5d344878ce0c3a3f45d881ef5dad460861fead65 Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Wed, 4 Apr 2018 10:09:19 +0800 Subject: [PATCH 15/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=80=A7=E9=97=AE=E9=A2=98=EF=BC=88=E5=8E=9F=E6=9D=A5=E7=9A=84?= =?UTF-8?q?=E5=86=99=E6=B3=95=E4=B8=8D=E5=85=BC=E5=AE=B9JDK6=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/alipay/jarslink/api/impl/ModuleClassLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleClassLoader.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleClassLoader.java index 722234c..5494b04 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleClassLoader.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleClassLoader.java @@ -49,7 +49,7 @@ public class ModuleClassLoader extends URLClassLoader { /** * 需要排除的包 */ - private final Set excludedPackages = new HashSet<>(); + private final Set excludedPackages = new HashSet(); /** * 需要子加载器优先加载的包 From fef26dabbbd218f146224c84c959a641ed86af0d Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Wed, 4 Apr 2018 11:33:11 +0800 Subject: [PATCH 16/24] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E6=97=B6=E7=9A=84=E6=8B=A6=E6=88=AA=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jarslink/api/ApplicationContextAware.java | 19 ++++ .../api/ApplicationContextPostProcessor.java | 19 ++++ .../alipay/jarslink/api/JarslinkAware.java | 10 ++ .../jarslink/api/JarslinkPostProcessor.java | 10 ++ .../com/alipay/jarslink/api/ModuleAware.java | 16 +++ .../com/alipay/jarslink/api/ModuleLoader.java | 56 ++++++++++- .../jarslink/api/ModulePostProcessor.java | 17 ++++ .../jarslink/api/impl/ModuleLoaderImpl.java | 97 +++++++++++++++++-- 8 files changed, 237 insertions(+), 7 deletions(-) create mode 100644 jarslink-api/src/main/java/com/alipay/jarslink/api/ApplicationContextAware.java create mode 100644 jarslink-api/src/main/java/com/alipay/jarslink/api/ApplicationContextPostProcessor.java create mode 100644 jarslink-api/src/main/java/com/alipay/jarslink/api/JarslinkAware.java create mode 100644 jarslink-api/src/main/java/com/alipay/jarslink/api/JarslinkPostProcessor.java create mode 100644 jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleAware.java create mode 100644 jarslink-api/src/main/java/com/alipay/jarslink/api/ModulePostProcessor.java diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/ApplicationContextAware.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/ApplicationContextAware.java new file mode 100644 index 0000000..43875f5 --- /dev/null +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/ApplicationContextAware.java @@ -0,0 +1,19 @@ +package com.alipay.jarslink.api; + +import org.springframework.context.ConfigurableApplicationContext; + +/** + * 加载模块时在创建完模块的spring-context后刷新spring-context前调用,用于做一些拦截处理 + * + * @author joe + * @version 2018.04.04 10:54 + */ +public interface ApplicationContextAware extends JarslinkAware{ + /** + * 加载模块时在创建完模块的spring-context后刷新spring-context前调用 + * + * @param context 当前加载的模块对应的configurableApplicationContext + * @param moduleConfig 当前加载的模块对应的配置 + */ + void setConfigurableApplicationContext(ConfigurableApplicationContext context, ModuleConfig moduleConfig); +} diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/ApplicationContextPostProcessor.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/ApplicationContextPostProcessor.java new file mode 100644 index 0000000..cb63bdb --- /dev/null +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/ApplicationContextPostProcessor.java @@ -0,0 +1,19 @@ +package com.alipay.jarslink.api; + +import org.springframework.context.ConfigurableApplicationContext; + +/** + * 加载模块时在创建完模块的spring-context并且刷新spring-context后调用,用于做一些拦截处理 + * + * @author joe + * @version 2018.04.04 10:53 + */ +public interface ApplicationContextPostProcessor extends JarslinkPostProcessor { + /** + * 加载模块时在创建完模块的spring-context并且刷新spring-context后调用 + * + * @param context 当前加载的模块对应的configurableApplicationContext + * @param moduleConfig 当前加载的模块对应的配置 + */ + void setConfigurableApplicationContext(ConfigurableApplicationContext context, ModuleConfig moduleConfig); +} diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/JarslinkAware.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/JarslinkAware.java new file mode 100644 index 0000000..bbe69cb --- /dev/null +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/JarslinkAware.java @@ -0,0 +1,10 @@ +package com.alipay.jarslink.api; + +/** + * 所有Aware的顶级接口 + * + * @author joe + * @version 2018.04.04 11:05 + */ +public interface JarslinkAware { +} diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/JarslinkPostProcessor.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/JarslinkPostProcessor.java new file mode 100644 index 0000000..71794d2 --- /dev/null +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/JarslinkPostProcessor.java @@ -0,0 +1,10 @@ +package com.alipay.jarslink.api; + +/** + * 所有PostProcessor的顶级接口 + * + * @author joe + * @version 2018.04.04 11:06 + */ +public interface JarslinkPostProcessor { +} diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleAware.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleAware.java new file mode 100644 index 0000000..555268b --- /dev/null +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleAware.java @@ -0,0 +1,16 @@ +package com.alipay.jarslink.api; + +/** + * 在加载模块前调用 + * + * @author joe + * @version 2018.04.04 10:59 + */ +public interface ModuleAware extends JarslinkAware { + /** + * 加载模块前调用 + * + * @param moduleConfig 模块配置 + */ + void setModuleConfig(ModuleConfig moduleConfig); +} diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleLoader.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleLoader.java index 461c321..e0e6081 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleLoader.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleLoader.java @@ -29,7 +29,6 @@ public interface ModuleLoader { * 根据配置加载一个模块,创建一个新的ClassLoadr加载jar里的class,初始化Spring ApplicationContext等 * * @param moduleConfig 模块配置信息 - * * @return 加载成功的模块 */ Module load(ModuleConfig moduleConfig); @@ -41,4 +40,59 @@ public interface ModuleLoader { */ void unload(Module module); + /** + * 注册ApplicationContext前置处理器 + * + * @param aware 要注册的前置处理器 + */ + void registerAware(ApplicationContextAware aware); + + /** + * 注册Module前置处理器 + * + * @param aware 要注册的前置处理器 + */ + void registerAware(ModuleAware aware); + + /** + * 注册ApplicationContext后处理器 + * + * @param postProcessor 要注册的后处理器 + */ + void registerPostProcessor(ApplicationContextPostProcessor postProcessor); + + /** + * 注册Module后处理器 + * + * @param postProcessor 要注册的后处理器 + */ + void registerPostProcessor(ModulePostProcessor postProcessor); + + /** + * 移除ApplicationContext前置处理器 + * + * @param aware 要移除的前置处理器 + */ + void unRegisterAware(ApplicationContextAware aware); + + /** + * 移除Module前置处理器 + * + * @param aware 要移除的前置处理器 + */ + void unRegisterAware(ModuleAware aware); + + /** + * 移除ApplicationContext后处理器 + * + * @param postProcessor 要移除的后处理器 + */ + void unRegisterPostProcessor(ApplicationContextPostProcessor postProcessor); + + /** + * 移除Module后处理器 + * + * @param postProcessor 要移除的后处理器 + */ + void unRegisterPostProcessor(ModulePostProcessor postProcessor); } diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModulePostProcessor.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModulePostProcessor.java new file mode 100644 index 0000000..5190347 --- /dev/null +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModulePostProcessor.java @@ -0,0 +1,17 @@ +package com.alipay.jarslink.api; + +/** + * module创建完后会调用该回调 + * + * @author joe + * @version 2018.04.04 11:01 + */ +public interface ModulePostProcessor extends JarslinkPostProcessor { + /** + * module创建完后调用 + * + * @param module 模块 + * @param moduleConfig 模块对应的配置 + */ + void setModule(Module module, ModuleConfig moduleConfig); +} diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleLoaderImpl.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleLoaderImpl.java index 991998f..23bee82 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleLoaderImpl.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleLoaderImpl.java @@ -17,9 +17,7 @@ */ package com.alipay.jarslink.api.impl; -import com.alipay.jarslink.api.Module; -import com.alipay.jarslink.api.ModuleConfig; -import com.alipay.jarslink.api.ModuleLoader; +import com.alipay.jarslink.api.*; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; @@ -41,6 +39,7 @@ import java.util.Map.Entry; import java.util.Properties; import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -60,7 +59,8 @@ public class ModuleLoaderImpl implements ModuleLoader, ApplicationContextAware { /** * Spring bean文件所在目录,不同的路径确保能取到资源 */ - private static String[] SPRING_XML_PATTERN = {"classpath*:META-INF/spring/*.xml", "classpath*:*META-INF/spring/*.xml"}; + private static String[] SPRING_XML_PATTERN = {"classpath*:META-INF/spring/*.xml", "classpath*:*META-INF/spring/*" + + ".xml"}; /** * 模块版本属性 @@ -82,6 +82,13 @@ public class ModuleLoaderImpl implements ModuleLoader, ApplicationContextAware { */ private ApplicationContext applicationContext; + private final List applicationContextAwares = new + CopyOnWriteArrayList(); + private final List moduleAwares = new CopyOnWriteArrayList(); + private final List applicationContextPostProcessors = new + CopyOnWriteArrayList(); + private final List modulePostProcessors = new CopyOnWriteArrayList(); + @Override public Module load(ModuleConfig moduleConfig) { if (LOGGER.isInfoEnabled()) { @@ -92,13 +99,17 @@ public Module load(ModuleConfig moduleConfig) { LOGGER.info("Local jars: {}", tempFileJarURLs); } + doModuleAware(moduleConfig); + ConfigurableApplicationContext moduleApplicationContext = loadModuleApplication(moduleConfig, tempFileJarURLs); if (LOGGER.isInfoEnabled()) { LOGGER.info("Loading module complete:{}", moduleConfig); } - return new SpringModule(moduleConfig, moduleConfig.getVersion(), moduleConfig.getName(), + Module module = new SpringModule(moduleConfig, moduleConfig.getVersion(), moduleConfig.getName(), moduleApplicationContext); + doModulePostProcessor(module, moduleConfig); + return module; } @Override @@ -108,6 +119,78 @@ public void unload(Module module) { } } + @Override + public void registerAware(com.alipay.jarslink.api.ApplicationContextAware aware) { + checkArgument(aware == null, "aware must be not null"); + applicationContextAwares.add(aware); + } + + @Override + public void registerAware(ModuleAware aware) { + checkArgument(aware == null, "aware must be not null"); + moduleAwares.add(aware); + } + + @Override + public void registerPostProcessor(ApplicationContextPostProcessor postProcessor) { + checkArgument(postProcessor == null, "PostProcessor must be not null"); + applicationContextPostProcessors.add(postProcessor); + } + + @Override + public void registerPostProcessor(ModulePostProcessor postProcessor) { + checkArgument(postProcessor == null, "PostProcessor must be not null"); + modulePostProcessors.add(postProcessor); + } + + @Override + public void unRegisterAware(com.alipay.jarslink.api.ApplicationContextAware aware) { + if (aware == null) return; + applicationContextAwares.remove(aware); + } + + @Override + public void unRegisterAware(ModuleAware aware) { + if (aware == null) return; + moduleAwares.remove(aware); + } + + @Override + public void unRegisterPostProcessor(ApplicationContextPostProcessor postProcessor) { + if (postProcessor == null) return; + applicationContextPostProcessors.remove(postProcessor); + } + + @Override + public void unRegisterPostProcessor(ModulePostProcessor postProcessor) { + if (postProcessor == null) return; + modulePostProcessors.remove(postProcessor); + } + + private void doApplicationContextAware(ConfigurableApplicationContext context, ModuleConfig moduleConfig) { + for (com.alipay.jarslink.api.ApplicationContextAware aware : applicationContextAwares) { + aware.setConfigurableApplicationContext(context, moduleConfig); + } + } + + private void doModuleAware(ModuleConfig moduleConfig) { + for (ModuleAware aware : moduleAwares) { + aware.setModuleConfig(moduleConfig); + } + } + + private void doApplicationContextPostProcessor(ConfigurableApplicationContext context, ModuleConfig moduleConfig) { + for (ApplicationContextPostProcessor postProcessor : applicationContextPostProcessors) { + postProcessor.setConfigurableApplicationContext(context, moduleConfig); + } + } + + private void doModulePostProcessor(Module module, ModuleConfig moduleConfig) { + for (ModulePostProcessor postProcessor : modulePostProcessors) { + postProcessor.setModule(module, moduleConfig); + } + } + /** * 根据本地临时文件Jar,初始化模块自己的ClassLoader,初始化Spring Application Context,同时要设置当前线程上下文的ClassLoader问模块的ClassLoader * @@ -149,7 +232,9 @@ private ConfigurableApplicationContext loadModuleApplication(ModuleConfig module moduleConfig.getVersion()); } ((DefaultResourceLoader) context).setClassLoader(moduleClassLoader); + doApplicationContextAware(context, moduleConfig); context.refresh(); + doApplicationContextPostProcessor(context, moduleConfig); return context; } catch (Throwable e) { CachedIntrospectionResults.clearClassLoader(moduleClassLoader); @@ -203,7 +288,7 @@ private String[] findSpringConfigs(List tempFileJarURLs, ClassLoader mod try { PathMatchingResourcePatternResolver pmr = new PathMatchingResourcePatternResolver(moduleClassLoader); Resource[] resources = ImmutableSet.builder().add(pmr.getResources(SPRING_XML_PATTERN[0])).add(pmr - .getResources(SPRING_XML_PATTERN[1])).build().toArray(new Resource[] {}); + .getResources(SPRING_XML_PATTERN[1])).build().toArray(new Resource[]{}); checkNotNull(resources, "resources is null"); checkArgument(resources.length > 0, "resources length is 0"); // 因为ClassLoader是树形结构,这里会找到ModuleClassLoader以及其父类中所有符合规范的spring配置文件,所以这里需要过滤,只需要Module Jar中的 From a402b942c648a8feca4fc9978064c11ef848adb7 Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Wed, 4 Apr 2018 13:44:42 +0800 Subject: [PATCH 17/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=80=A7=E9=97=AE=E9=A2=98=EF=BC=88=E9=83=A8=E5=88=86=E8=AF=AD?= =?UTF-8?q?=E6=B3=95=E4=B8=8D=E5=85=BC=E5=AE=B9JDK6=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/alipay/jarslink/api/ModuleConfig.java | 12 +++++++++--- .../api/impl/AbstractModuleRefreshScheduler.java | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleConfig.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleConfig.java index 14ed128..aef7146 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleConfig.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/ModuleConfig.java @@ -17,6 +17,7 @@ */ package com.alipay.jarslink.api; +import com.google.common.base.Function; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -28,7 +29,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; -import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; @@ -62,7 +62,7 @@ public class ModuleConfig extends ToStringObject { *

* xml中的bean不能依赖注解bean,注解bean可以依赖xml定义的bean */ - private Set scanPackages = new CopyOnWriteArraySet<>(); + private Set scanPackages = new CopyOnWriteArraySet(); /** * 模块的版本,如1.0.0.20120609 版本变化会触发模块重新部署 @@ -102,7 +102,13 @@ public List getModuleUrl() { public List getModuleUrlPath() { List moduleUrls = Lists.newArrayList(); - moduleUrls.addAll(moduleUrl.stream().map(URL::toString).collect(Collectors.toList())); + List list = Lists.transform(moduleUrl, new Function() { + @Override + public String apply(URL input) { + return input.toString(); + } + }); + moduleUrls.addAll(list); return moduleUrls; } diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/AbstractModuleRefreshScheduler.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/AbstractModuleRefreshScheduler.java index 27c7055..8fd6fc4 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/AbstractModuleRefreshScheduler.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/AbstractModuleRefreshScheduler.java @@ -174,7 +174,7 @@ private void refreshModuleConfigs() { private Collection filterEnabledModule() { List moduleConfigs = queryModuleConfigs(); if (moduleConfigs == null || moduleConfigs.isEmpty()) { - return new ArrayList<>(); + return new ArrayList(); } return Collections2.filter(moduleConfigs, new Predicate() { @Override From 8fc3457c8a1aa47576cacd169e785b164913a309 Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Wed, 4 Apr 2018 13:45:27 +0800 Subject: [PATCH 18/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=A4=E6=96=ADBUG?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jarslink/api/impl/ModuleLoaderImpl.java | 8 +- .../api/impl/ApplicationContextAwareImpl.java | 21 +++ .../ApplicationContextPostProcessorImpl.java | 21 +++ .../jarslink/api/impl/ModuleAwareImpl.java | 19 +++ .../api/impl/ModuleLoaderInjectTest.java | 131 ++++++++++++++++++ .../api/impl/ModulePostProcessorImpl.java | 21 +++ 6 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ApplicationContextAwareImpl.java create mode 100644 jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ApplicationContextPostProcessorImpl.java create mode 100644 jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleAwareImpl.java create mode 100644 jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleLoaderInjectTest.java create mode 100644 jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModulePostProcessorImpl.java diff --git a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleLoaderImpl.java b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleLoaderImpl.java index 23bee82..7c8cfc7 100644 --- a/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleLoaderImpl.java +++ b/jarslink-api/src/main/java/com/alipay/jarslink/api/impl/ModuleLoaderImpl.java @@ -121,25 +121,25 @@ public void unload(Module module) { @Override public void registerAware(com.alipay.jarslink.api.ApplicationContextAware aware) { - checkArgument(aware == null, "aware must be not null"); + checkArgument(aware != null, "aware must be not null"); applicationContextAwares.add(aware); } @Override public void registerAware(ModuleAware aware) { - checkArgument(aware == null, "aware must be not null"); + checkArgument(aware != null, "aware must be not null"); moduleAwares.add(aware); } @Override public void registerPostProcessor(ApplicationContextPostProcessor postProcessor) { - checkArgument(postProcessor == null, "PostProcessor must be not null"); + checkArgument(postProcessor != null, "PostProcessor must be not null"); applicationContextPostProcessors.add(postProcessor); } @Override public void registerPostProcessor(ModulePostProcessor postProcessor) { - checkArgument(postProcessor == null, "PostProcessor must be not null"); + checkArgument(postProcessor != null, "PostProcessor must be not null"); modulePostProcessors.add(postProcessor); } diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ApplicationContextAwareImpl.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ApplicationContextAwareImpl.java new file mode 100644 index 0000000..fd094c9 --- /dev/null +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ApplicationContextAwareImpl.java @@ -0,0 +1,21 @@ +package com.alipay.jarslink.api.impl; + +import com.alipay.jarslink.api.ApplicationContextAware; +import com.alipay.jarslink.api.ModuleConfig; +import org.junit.Assert; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * 测试用 + * + * @author joe + * @version 2018.04.04 11:44 + */ +public class ApplicationContextAwareImpl implements ApplicationContextAware { + @Override + public void setConfigurableApplicationContext(ConfigurableApplicationContext context, ModuleConfig moduleConfig) { + moduleConfig.withVersion("2.0"); + Assert.assertNotNull(context); + Assert.assertNotNull(moduleConfig); + } +} diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ApplicationContextPostProcessorImpl.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ApplicationContextPostProcessorImpl.java new file mode 100644 index 0000000..183f9f4 --- /dev/null +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ApplicationContextPostProcessorImpl.java @@ -0,0 +1,21 @@ +package com.alipay.jarslink.api.impl; + +import com.alipay.jarslink.api.ApplicationContextPostProcessor; +import com.alipay.jarslink.api.ModuleConfig; +import org.junit.Assert; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * 测试用 + * + * @author joe + * @version 2018.04.04 11:44 + */ +public class ApplicationContextPostProcessorImpl implements ApplicationContextPostProcessor { + @Override + public void setConfigurableApplicationContext(ConfigurableApplicationContext context, ModuleConfig moduleConfig) { + moduleConfig.withVersion("2.0"); + Assert.assertNotNull(context); + Assert.assertNotNull(moduleConfig); + } +} diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleAwareImpl.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleAwareImpl.java new file mode 100644 index 0000000..2f8a6ca --- /dev/null +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleAwareImpl.java @@ -0,0 +1,19 @@ +package com.alipay.jarslink.api.impl; + +import com.alipay.jarslink.api.ModuleAware; +import com.alipay.jarslink.api.ModuleConfig; +import org.junit.Assert; + +/** + * 测试用 + * + * @author joe + * @version 2018.04.04 11:47 + */ +public class ModuleAwareImpl implements ModuleAware { + @Override + public void setModuleConfig(ModuleConfig moduleConfig) { + moduleConfig.withVersion("2.0"); + Assert.assertNotNull(moduleConfig); + } +} diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleLoaderInjectTest.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleLoaderInjectTest.java new file mode 100644 index 0000000..e8e1c35 --- /dev/null +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModuleLoaderInjectTest.java @@ -0,0 +1,131 @@ +package com.alipay.jarslink.api.impl; + +import com.alipay.jarslink.api.*; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.concurrent.Semaphore; + +import static com.alipay.jarslink.api.impl.ModuleLoaderImplTest.buildModuleConfig; + +/** + * @author joe + * @version 2018.04.04 11:38 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath*:META-INF/spring/jarslink.xml"}) +public class ModuleLoaderInjectTest { + @Autowired + private ModuleLoader moduleLoader; + private Semaphore semaphore = new Semaphore(1); + + @Test + public void shouldRegisterApplicationContextAware() throws InterruptedException { + semaphore.acquire(); + ApplicationContextAware aware = new ApplicationContextAwareImpl(); + moduleLoader.registerAware(aware); + ModuleConfig config = buildModuleConfig("demo", "1.0", true); + Module module = moduleLoader.load(config); + Assert.assertNotNull(module); + Assert.assertEquals("2.0", config.getVersion()); + moduleLoader.unRegisterAware(aware); + semaphore.release(); + } + + @Test + public void shouldRegisterModuleAware() throws InterruptedException { + semaphore.acquire(); + ModuleAware aware = new ModuleAwareImpl(); + moduleLoader.registerAware(aware); + ModuleConfig config = buildModuleConfig("demo", "1.0", true); + Module module = moduleLoader.load(config); + Assert.assertNotNull(module); + Assert.assertEquals("2.0", module.getModuleConfig().getVersion()); + moduleLoader.unRegisterAware(aware); + semaphore.release(); + } + + @Test + public void shouldRegisterApplicationContextPostProcessor() throws InterruptedException { + semaphore.acquire(); + ApplicationContextPostProcessor postProcessor = new ApplicationContextPostProcessorImpl(); + moduleLoader.registerPostProcessor(postProcessor); + ModuleConfig config = buildModuleConfig("demo", "1.0", true); + Module module = moduleLoader.load(config); + Assert.assertNotNull(module); + Assert.assertEquals("2.0", config.getVersion()); + moduleLoader.unRegisterPostProcessor(postProcessor); + semaphore.release(); + } + + @Test + public void shouldRegisterModulePostProcessor() throws InterruptedException { + semaphore.acquire(); + ModulePostProcessor postProcessor = new ModulePostProcessorImpl(); + moduleLoader.registerPostProcessor(postProcessor); + ModuleConfig config = buildModuleConfig("demo", "1.0", true); + Module module = moduleLoader.load(config); + Assert.assertNotNull(module); + Assert.assertEquals("2.0", config.getVersion()); + moduleLoader.unRegisterPostProcessor(postProcessor); + semaphore.release(); + } + + @Test + public void shouldUnRegisterApplicationContextAware() throws InterruptedException { + semaphore.acquire(); + ApplicationContextAware aware = new ApplicationContextAwareImpl(); + moduleLoader.registerAware(aware); + moduleLoader.unRegisterAware(aware); + + ModuleConfig config = buildModuleConfig("demo", "1.0", true); + Module module = moduleLoader.load(config); + Assert.assertNotNull(module); + Assert.assertEquals("1.0", config.getVersion()); + semaphore.release(); + } + + @Test + public void shouldUnRegisterModuleAware() throws InterruptedException { + semaphore.acquire(); + ModuleAware aware = new ModuleAwareImpl(); + moduleLoader.registerAware(aware); + moduleLoader.unRegisterAware(aware); + + ModuleConfig config = buildModuleConfig("demo", "1.0", true); + Module module = moduleLoader.load(config); + Assert.assertNotNull(module); + Assert.assertEquals("1.0", module.getModuleConfig().getVersion()); + semaphore.release(); + } + + @Test + public void shouldUnRegisterApplicationContextPostProcessor() throws InterruptedException { + semaphore.acquire(); + ApplicationContextPostProcessor postProcessor = new ApplicationContextPostProcessorImpl(); + moduleLoader.registerPostProcessor(postProcessor); + moduleLoader.unRegisterPostProcessor(postProcessor); + ModuleConfig config = buildModuleConfig("demo", "1.0", true); + Module module = moduleLoader.load(config); + Assert.assertNotNull(module); + Assert.assertEquals("1.0", config.getVersion()); + semaphore.release(); + } + + @Test + public void shouldUnRegisterModulePostProcessor() throws InterruptedException { + semaphore.acquire(); + ModulePostProcessor postProcessor = new ModulePostProcessorImpl(); + moduleLoader.registerPostProcessor(postProcessor); + moduleLoader.unRegisterPostProcessor(postProcessor); + ModuleConfig config = buildModuleConfig("demo", "1.0", true); + Module module = moduleLoader.load(config); + Assert.assertNotNull(module); + Assert.assertEquals("1.0", config.getVersion()); + semaphore.release(); + } +} diff --git a/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModulePostProcessorImpl.java b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModulePostProcessorImpl.java new file mode 100644 index 0000000..faeaa16 --- /dev/null +++ b/jarslink-api/src/test/java/com/alipay/jarslink/api/impl/ModulePostProcessorImpl.java @@ -0,0 +1,21 @@ +package com.alipay.jarslink.api.impl; + +import com.alipay.jarslink.api.Module; +import com.alipay.jarslink.api.ModuleConfig; +import com.alipay.jarslink.api.ModulePostProcessor; +import org.junit.Assert; + +/** + * 测试用 + * + * @author joe + * @version 2018.04.04 11:44 + */ +public class ModulePostProcessorImpl implements ModulePostProcessor { + @Override + public void setModule(Module module, ModuleConfig moduleConfig) { + moduleConfig.withVersion("2.0"); + Assert.assertNotNull(module); + Assert.assertNotNull(moduleConfig); + } +} From c1f24972c911c2786062da931975fd4abdecf208 Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Wed, 4 Apr 2018 13:49:43 +0800 Subject: [PATCH 19/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9POM=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=EF=BC=8C=E5=BC=BA=E5=88=B6=E5=AE=9A=E4=B9=89=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E7=BC=96=E8=AF=91JDK=E7=89=88=E6=9C=AC=E4=B8=BA1.6=EF=BC=88?= =?UTF-8?q?=E5=8E=9F=E6=9D=A5=E4=B8=BA=E5=86=99=E6=AD=BB=E7=9A=841.8?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jarslink-api/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jarslink-api/pom.xml b/jarslink-api/pom.xml index d28d5b1..8ddb3a4 100644 --- a/jarslink-api/pom.xml +++ b/jarslink-api/pom.xml @@ -167,8 +167,8 @@ maven-compiler-plugin 2.0.2 - 1.8 - 1.8 + ${java.version} + ${java.version} UTF-8 From 76718a6a009d8e30bb01d6356875d641b18d782e Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Wed, 4 Apr 2018 15:23:00 +0800 Subject: [PATCH 20/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E9=97=B4=E8=B0=83=E7=94=A8=EF=BC=88=E5=BD=93=E5=89=8D=E5=8F=AA?= =?UTF-8?q?=E6=9C=89=E5=9C=A8=E6=A8=A1=E5=9D=97=E4=BD=BF=E7=94=A8=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3=E7=9A=84=E5=BD=A2=E5=BC=8F=E6=97=B6=E6=89=8D=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=89=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E9=97=B4=E8=B0=83=E7=94=A8=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jarslink-inject/pom.xml | 66 ++++ .../alipay/jarslink/support/ActionBean.java | 64 ++++ .../jarslink/support/ActionFactoryBean.java | 55 ++++ .../ReferenceAnnotationBeanPostProcessor.java | 291 ++++++++++++++++++ .../com/alipay/jarslink/support/Utils.java | 21 ++ .../support/annotation/ActionReference.java | 35 +++ .../support/ApplicationContextAwareImpl.java | 31 ++ ...erenceAnnotationBeanPostProcessorTest.java | 71 +++++ .../resources/META-INF/spring/jarslink.xml | 22 ++ .../resources/jarslink-module-a-1.0.0.jar | Bin 0 -> 3900 bytes .../resources/jarslink-module-b-1.0.0.jar | Bin 0 -> 3900 bytes jarslink-module-a/pom.xml | 43 +++ .../jarslink/demo/annotation/AAction.java | 21 ++ .../jarslink/demo/annotation/ActionProxy.java | 27 ++ jarslink-module-b/pom.xml | 42 +++ .../jarslink/demo/annotation/ActionProxy.java | 27 ++ .../jarslink/demo/annotation/BAction.java | 21 ++ 17 files changed, 837 insertions(+) create mode 100644 jarslink-inject/pom.xml create mode 100644 jarslink-inject/src/main/java/com/alipay/jarslink/support/ActionBean.java create mode 100644 jarslink-inject/src/main/java/com/alipay/jarslink/support/ActionFactoryBean.java create mode 100644 jarslink-inject/src/main/java/com/alipay/jarslink/support/ReferenceAnnotationBeanPostProcessor.java create mode 100644 jarslink-inject/src/main/java/com/alipay/jarslink/support/Utils.java create mode 100644 jarslink-inject/src/main/java/com/alipay/jarslink/support/annotation/ActionReference.java create mode 100644 jarslink-inject/src/test/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java create mode 100644 jarslink-inject/src/test/java/com/alipay/jarslink/support/ReferenceAnnotationBeanPostProcessorTest.java create mode 100644 jarslink-inject/src/test/resources/META-INF/spring/jarslink.xml create mode 100644 jarslink-inject/src/test/resources/jarslink-module-a-1.0.0.jar create mode 100644 jarslink-inject/src/test/resources/jarslink-module-b-1.0.0.jar create mode 100644 jarslink-module-a/pom.xml create mode 100644 jarslink-module-a/src/main/java/com/alipay/jarslink/demo/annotation/AAction.java create mode 100644 jarslink-module-a/src/main/java/com/alipay/jarslink/demo/annotation/ActionProxy.java create mode 100644 jarslink-module-b/pom.xml create mode 100644 jarslink-module-b/src/main/java/com/alipay/jarslink/demo/annotation/ActionProxy.java create mode 100644 jarslink-module-b/src/main/java/com/alipay/jarslink/demo/annotation/BAction.java diff --git a/jarslink-inject/pom.xml b/jarslink-inject/pom.xml new file mode 100644 index 0000000..f3f90ae --- /dev/null +++ b/jarslink-inject/pom.xml @@ -0,0 +1,66 @@ + + + + + 4.0.0 + com.alipay.jarslink.support + jarslink-inject + 1.0.0.20180403 + Alipay JarsLink Support + https://github.com/alibaba/jarslink + jar + Alipay JarsLink Support + + + 4.3.10.RELEASE + 1.7.0.20180401 + 1.6 + + + + + org.springframework + spring-beans + ${org.springframework.version} + + + org.springframework + spring-context + ${org.springframework.version} + + + com.alipay.jarslink + jarslink-api + ${jarslink.version} + + + junit + junit + 4.12 + test + + + org.springframework + spring-test + ${org.springframework.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + ${java.version} + ${java.version} + UTF-8 + + + + + \ No newline at end of file diff --git a/jarslink-inject/src/main/java/com/alipay/jarslink/support/ActionBean.java b/jarslink-inject/src/main/java/com/alipay/jarslink/support/ActionBean.java new file mode 100644 index 0000000..f14e5fd --- /dev/null +++ b/jarslink-inject/src/main/java/com/alipay/jarslink/support/ActionBean.java @@ -0,0 +1,64 @@ +package com.alipay.jarslink.support; + +import com.alipay.jarslink.api.Action; +import com.alipay.jarslink.api.Module; +import com.alipay.jarslink.api.ModuleManager; +import com.alipay.jarslink.support.annotation.ActionReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * action bean + * + * @author joe + * @version 2018.04.03 17:17 + */ +public class ActionBean implements Action { + private static final Logger LOGGER = LoggerFactory.getLogger(ActionBean.class); + private final ModuleManager moduleManager; + private final ActionReference reference; + private String version; + private String moduleName; + private String actionName; + + public ActionBean(ModuleManager moduleManager, ActionReference reference) { + this.moduleManager = moduleManager; + this.reference = reference; + init(); + } + + private void init() { + version = reference.version(); + moduleName = reference.moduleName(); + actionName = reference.name(); + Utils.checkEmpty(version, "module version must not be null or empty"); + Utils.checkEmpty(moduleName, "module version must not be null or empty"); + Utils.checkEmpty(actionName, "module version must not be null or empty"); + } + + @Override + public Object execute(Object t) { + Module module = moduleManager.find(moduleName, version); + if (module == null) { + LOGGER.error("module[" + moduleName + ":" + version + "] not exist"); + throw new IllegalStateException("module[" + moduleName + ":" + version + "] not exist"); + } + Action action = null; + try { + action = module.getAction(actionName); + } catch (NullPointerException e) { + if (action == null) { + LOGGER.error("action[" + moduleName + ":" + version + ":" + actionName + "] not exist"); + throw new IllegalStateException("action[" + moduleName + ":" + version + ":" + actionName + "] not " + + "exist"); + } + } + + return action.execute(t); + } + + @Override + public String getActionName() { + return actionName; + } +} diff --git a/jarslink-inject/src/main/java/com/alipay/jarslink/support/ActionFactoryBean.java b/jarslink-inject/src/main/java/com/alipay/jarslink/support/ActionFactoryBean.java new file mode 100644 index 0000000..4ff2235 --- /dev/null +++ b/jarslink-inject/src/main/java/com/alipay/jarslink/support/ActionFactoryBean.java @@ -0,0 +1,55 @@ +package com.alipay.jarslink.support; + +import com.alipay.jarslink.api.ModuleManager; +import com.alipay.jarslink.support.annotation.ActionReference; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * @author joe + * @version 2018.04.03 16:45 + */ +public class ActionFactoryBean implements FactoryBean, ApplicationContextAware, DisposableBean { + private List actionBeans = new CopyOnWriteArrayList(); + private ModuleManager moduleManager; + private ActionReference reference; + private ActionBean ref; + + public ActionFactoryBean(ModuleManager moduleManager, ActionReference reference) { + this.moduleManager = moduleManager; + this.reference = reference; + this.ref = new ActionBean(moduleManager, reference); + } + + @Override + public void destroy() throws Exception { + ref = null; + } + + @Override + public Object getObject() throws Exception { + return ref; + } + + @Override + public Class getObjectType() { + return ActionBean.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + + } +} diff --git a/jarslink-inject/src/main/java/com/alipay/jarslink/support/ReferenceAnnotationBeanPostProcessor.java b/jarslink-inject/src/main/java/com/alipay/jarslink/support/ReferenceAnnotationBeanPostProcessor.java new file mode 100644 index 0000000..e9461c2 --- /dev/null +++ b/jarslink-inject/src/main/java/com/alipay/jarslink/support/ReferenceAnnotationBeanPostProcessor.java @@ -0,0 +1,291 @@ +package com.alipay.jarslink.support; + +import com.alipay.jarslink.api.ModuleManager; +import com.alipay.jarslink.support.annotation.ActionReference; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.annotation.InjectionMetadata; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.core.PriorityOrdered; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static org.springframework.core.BridgeMethodResolver.findBridgedMethod; +import static org.springframework.core.BridgeMethodResolver.isVisibilityBridgeMethodPair; +import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; +import static org.springframework.core.annotation.AnnotationUtils.getAnnotation; + +/** + * 处理使用注解上下文的action注入问题 + * + * @author joe + * @version 2018.04.03 16:41 + */ +public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter + implements MergedBeanDefinitionPostProcessor, PriorityOrdered, DisposableBean { + /** + * The bean name of {@link ReferenceAnnotationBeanPostProcessor} + */ + public static final String BEAN_NAME = "referenceAnnotationBeanPostProcessor"; + + private final Log logger = LogFactory.getLog(getClass()); + + private ModuleManager moduleManager; + + public ReferenceAnnotationBeanPostProcessor(ModuleManager moduleManager) { + this.moduleManager = moduleManager; + } + + + private final ConcurrentMap injectionMetadataCache = + new ConcurrentHashMap(256); + + private final ConcurrentMap referenceBeansCache = + new ConcurrentHashMap(); + + @Override + public PropertyValues postProcessPropertyValues( + PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { + + InjectionMetadata metadata = findReferenceMetadata(beanName, bean.getClass(), pvs); + try { + metadata.inject(bean, beanName, pvs); + } catch (BeanCreationException ex) { + throw ex; + } catch (Throwable ex) { + throw new BeanCreationException(beanName, "Injection of @ActionReference dependencies failed", ex); + } + return pvs; + } + + + /** + * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated + * {@link ActionReference @ActionReference} fields + * + * @param beanClass The {@link Class} of Bean + * @return non-null {@link List} + */ + private List findFieldReferenceMetadata(final Class beanClass) { + + final List elements = new LinkedList(); + + ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() { + @Override + public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { + ActionReference reference = getAnnotation(field, ActionReference.class); + + if (reference != null) { + + if (Modifier.isStatic(field.getModifiers())) { + if (logger.isWarnEnabled()) { + logger.warn("@ActionReference annotation is not supported on static fields: " + field); + } + return; + } + + elements.add(new ReferenceFieldElement(field, reference)); + } + } + }); + + return elements; + + } + + /** + * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated + * {@link ActionReference @ActionReference} methods + * + * @param beanClass The {@link Class} of Bean + * @return non-null {@link List} + */ + private List findMethodReferenceMetadata(final Class beanClass) { + + final List elements = new LinkedList(); + + ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() { + @Override + public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { + + + Method bridgedMethod = findBridgedMethod(method); + + if (!isVisibilityBridgeMethodPair(method, bridgedMethod)) { + return; + } + + ActionReference reference = findAnnotation(bridgedMethod, ActionReference.class); + + if (reference != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) { + if (Modifier.isStatic(method.getModifiers())) { + if (logger.isWarnEnabled()) { + logger.warn("@ActionReference annotation is not supported on static methods: " + method); + } + return; + } + if (method.getParameterTypes().length == 0) { + if (logger.isWarnEnabled()) { + logger.warn("@ActionReference annotation should only be used on methods with parameters:" + + " " + + method); + } + } + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass); + elements.add(new ReferenceMethodElement(method, pd, reference)); + } + } + }); + + return elements; + } + + + /** + * @param beanClass + * @return + */ + private InjectionMetadata buildReferenceMetadata(final Class beanClass) { + + final List elements = new LinkedList(); + + elements.addAll(findFieldReferenceMetadata(beanClass)); + + elements.addAll(findMethodReferenceMetadata(beanClass)); + + return new InjectionMetadata(beanClass, elements); + + } + + private InjectionMetadata findReferenceMetadata(String beanName, Class clazz, PropertyValues pvs) { + // Fall back to class name as cache key, for backwards compatibility with custom callers. + String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); + // Quick check on the concurrent map first, with minimal locking. + InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); + if (InjectionMetadata.needsRefresh(metadata, clazz)) { + synchronized (this.injectionMetadataCache) { + metadata = this.injectionMetadataCache.get(cacheKey); + if (InjectionMetadata.needsRefresh(metadata, clazz)) { + if (metadata != null) { + metadata.clear(pvs); + } + try { + metadata = buildReferenceMetadata(clazz); + this.injectionMetadataCache.put(cacheKey, metadata); + } catch (NoClassDefFoundError err) { + throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() + + "] for reference metadata: could not find class that it depends on", err); + } + } + } + } + return metadata; + } + + + @Override + public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { + if (beanType != null) { + InjectionMetadata metadata = findReferenceMetadata(beanName, beanType, null); + metadata.checkConfigMembers(beanDefinition); + } + } + + @Override + public int getOrder() { + return LOWEST_PRECEDENCE; + } + + @Override + public void destroy() throws Exception { + + for (ActionFactoryBean actionFactoryBean : referenceBeansCache.values()) { + if (logger.isInfoEnabled()) { + logger.info(actionFactoryBean + " was destroying!"); + } + actionFactoryBean.destroy(); + } + + injectionMetadataCache.clear(); + referenceBeansCache.clear(); + + if (logger.isInfoEnabled()) { + logger.info(getClass() + " was destroying!"); + } + } + + /** + * {@link ActionReference} {@link Method} {@link InjectionMetadata.InjectedElement} + */ + private class ReferenceMethodElement extends InjectionMetadata.InjectedElement { + + private final Method method; + + private final ActionReference reference; + + protected ReferenceMethodElement(Method method, PropertyDescriptor pd, ActionReference reference) { + super(method, pd); + this.method = method; + this.reference = reference; + } + + @Override + protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { + Object referenceBean = buildReferenceBean(reference); + ReflectionUtils.makeAccessible(method); + method.invoke(bean, referenceBean); + } + } + + /** + * {@link ActionReference} {@link Field} {@link InjectionMetadata.InjectedElement} + */ + private class ReferenceFieldElement extends InjectionMetadata.InjectedElement { + + private final Field field; + + private final ActionReference reference; + + protected ReferenceFieldElement(Field field, ActionReference reference) { + super(field, null); + this.field = field; + this.reference = reference; + } + + @Override + protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { + Object referenceBean = buildReferenceBean(reference); + ReflectionUtils.makeAccessible(field); + field.set(bean, referenceBean); + } + + } + + private Object buildReferenceBean(ActionReference reference) throws Exception { + String key = reference.moduleName() + ":" + reference.version() + "#" + reference.name(); + ActionFactoryBean bean = referenceBeansCache.get(key); + ActionFactoryBean old = null; + if (bean == null) { + bean = new ActionFactoryBean(moduleManager, reference); + old = referenceBeansCache.putIfAbsent(key, bean); + } + + return old == null ? bean.getObject() : old.getObject(); + } +} diff --git a/jarslink-inject/src/main/java/com/alipay/jarslink/support/Utils.java b/jarslink-inject/src/main/java/com/alipay/jarslink/support/Utils.java new file mode 100644 index 0000000..9630083 --- /dev/null +++ b/jarslink-inject/src/main/java/com/alipay/jarslink/support/Utils.java @@ -0,0 +1,21 @@ +package com.alipay.jarslink.support; + +/** + * 工具类 + * + * @author joe + * @version 2018.04.03 17:27 + */ +public class Utils { + /** + * 检查字符串非空,如果字符串是空则抛出异常 + * + * @param str 字符串 + * @param errorMsg 错误消息 + */ + public static void checkEmpty(String str, String errorMsg) { + if (str == null || str.trim().equals("")) { + throw new IllegalArgumentException(errorMsg); + } + } +} diff --git a/jarslink-inject/src/main/java/com/alipay/jarslink/support/annotation/ActionReference.java b/jarslink-inject/src/main/java/com/alipay/jarslink/support/annotation/ActionReference.java new file mode 100644 index 0000000..58be531 --- /dev/null +++ b/jarslink-inject/src/main/java/com/alipay/jarslink/support/annotation/ActionReference.java @@ -0,0 +1,35 @@ +package com.alipay.jarslink.support.annotation; + +import java.lang.annotation.*; + +/** + * 用于在模块中注入Action + * + * @author joe + * @version 2018.04.03 16:37 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +public @interface ActionReference { + /** + * module name + * + * @return module name + */ + String moduleName(); + + /** + * module version + * + * @return module version + */ + String version(); + + /** + * action name + * + * @return action name + */ + String name(); +} diff --git a/jarslink-inject/src/test/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java b/jarslink-inject/src/test/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java new file mode 100644 index 0000000..fe77bdf --- /dev/null +++ b/jarslink-inject/src/test/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java @@ -0,0 +1,31 @@ +package com.alipay.jarslink.support; + +import com.alipay.jarslink.api.ApplicationContextAware; +import com.alipay.jarslink.api.ModuleConfig; +import com.alipay.jarslink.api.ModuleManager; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * @author joe + * @version 2018.04.04 14:54 + */ +public class ApplicationContextAwareImpl implements ApplicationContextAware { + private final ReferenceAnnotationBeanPostProcessor postProcessor; + + public ApplicationContextAwareImpl(ModuleManager moduleManager) { + this.postProcessor = new ReferenceAnnotationBeanPostProcessor(moduleManager); + } + + @Override + public void setConfigurableApplicationContext(ConfigurableApplicationContext context, ModuleConfig moduleConfig) { + context.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() { + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + beanFactory.addBeanPostProcessor(postProcessor); + } + }); + } +} diff --git a/jarslink-inject/src/test/java/com/alipay/jarslink/support/ReferenceAnnotationBeanPostProcessorTest.java b/jarslink-inject/src/test/java/com/alipay/jarslink/support/ReferenceAnnotationBeanPostProcessorTest.java new file mode 100644 index 0000000..578b9e3 --- /dev/null +++ b/jarslink-inject/src/test/java/com/alipay/jarslink/support/ReferenceAnnotationBeanPostProcessorTest.java @@ -0,0 +1,71 @@ +package com.alipay.jarslink.support; + +import com.alipay.jarslink.api.*; +import com.google.common.collect.ImmutableList; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.net.URL; + +/** + * @author joe + * @version 2018.04.04 14:22 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath*:META-INF/spring/jarslink.xml"}) +public class ReferenceAnnotationBeanPostProcessorTest { + public static final String JARSLINK_MODULE_DEMO_A = "jarslink-module-a-1.0.0.jar"; + public static final String JARSLINK_MODULE_DEMO_B = "jarslink-module-b-1.0.0.jar"; + @Autowired + private ModuleManager moduleManager; + @Autowired + private ModuleLoader moduleLoader; + + @Before + public void init() { + ApplicationContextAware aware = new ApplicationContextAwareImpl(moduleManager); + moduleLoader.registerAware(aware); + } + + @Test + public void shouldInject() { + ModuleConfig configA = buildModuleConfig("demo-a", "1.0", true, JARSLINK_MODULE_DEMO_A); + ModuleConfig configB = buildModuleConfig("demo-b", "1.0", true, JARSLINK_MODULE_DEMO_B); + Module moduleA = moduleLoader.load(configA); + Module moduleB = moduleLoader.load(configB); + moduleManager.register(moduleA); + moduleManager.register(moduleB); + Assert.assertNotNull(moduleA); + Assert.assertNotNull(moduleB); + String result = moduleA.doAction("action-a", "request"); + Assert.assertEquals("a-request", result); + result = moduleB.doAction("action-b", "request"); + Assert.assertEquals("b-request", result); + + result = moduleB.doAction("proxy-action-a", "request"); + Assert.assertEquals("a-request", result); + + result = moduleA.doAction("proxy-action-b", "request"); + Assert.assertEquals("b-request", result); + } + + public static ModuleConfig buildModuleConfig(String name, String version, boolean enabled, String path) { + ModuleConfig moduleConfig = new ModuleConfig(); + //通过该方法构建的配置都是使用注解形式扫描bean的 + String scanBase = "com.alipay.jarslink.demo.annotation"; + moduleConfig.addScanPackage(scanBase); + + + moduleConfig.withEnabled(enabled).withName(name).withVersion(version).withOverridePackages(ImmutableList.of + ("com.alipay.jarslink.demo")); + URL demoModule = Thread.currentThread().getContextClassLoader().getResource(path); + + moduleConfig.setModuleUrl(ImmutableList.of(demoModule)); + return moduleConfig; + } +} diff --git a/jarslink-inject/src/test/resources/META-INF/spring/jarslink.xml b/jarslink-inject/src/test/resources/META-INF/spring/jarslink.xml new file mode 100644 index 0000000..9ecea98 --- /dev/null +++ b/jarslink-inject/src/test/resources/META-INF/spring/jarslink.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/jarslink-inject/src/test/resources/jarslink-module-a-1.0.0.jar b/jarslink-inject/src/test/resources/jarslink-module-a-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..26ae4c2ef11e42e65d08d72275d28406cd83021e GIT binary patch literal 3900 zcmbtW3pkVQ8(+?cmD7@A5*1}~i1MKs&0({!4V6QNIc~N#hdGv{!<1Ai$st+NL87n2 zC{c=>6Wgzrc#^E%0e2`km1>@iy);#*l1Q( z3Pu5i!Bz^TiXM2Rd_k(>0O3Nk)WevEF(+hsx@F$Ft;L4g`4)T-0)#x z3{w4w(?#D;c_aowIwBuMWvOFAODV#2f^k8xs z8m?apPQ6*_=sx6{*lO9e z?tg#}_;F5xJ)q}!2Vn1!9~{H&(jVP)bUOIQJ#5uRkZ*sKi@OUu?l2Z@k^wFUs|ybgyb1hD!FI^sxB|A3X9@xZ_4nQ<5#g?7>ydfPGH9 z*zKE%Pa9S@S-rSgdqC+}Ox|rw=#`#J@0~yOdp7DkNDI4^sMzw^zHihB&uhNtYSI6i z!umvgv;VRGi-(_MhLWZ9>TONcMR0q&E)*B3JW0*eDZTxrW^?JC7e*bsoL*Y>6xk{4 zT-RZiyQSB`Z>{H}!}VN~Z6R&7zQU)$H9j0OqA9)%g*)F=WLR3V>JwoY=Cj6L_r{v-(}nn!Z}mP^yo>}72&*` z6adz7PK0@Ev+A~i$hnk2o(#PfmpTfPbXurluu0?mfU|g8c0`oo>+Qk5%cfY@9|r#O zkZ;$MI~HcjVD7Gf#wPEQgE-*L}+k)=-H)u8dCRT`Pk^3@ub zdeD9Gt@p5Em&&|37&Gv(6ON=IgdX?qbK>CjlIBCrvVUYk5Qez^ixK#qly`}Rz0x**`(H<_8oL{2 z9p*0TjV3xM@G4pKH{k3%oQwDUPhQvXuktx@&P&_H&}`3MKX>lwi@eo#8)8-*R#jr> zYY0a>=GjvR6qIe-@(x*<_T9@j@65cwv&czIFW3P)?20X*?5p}#6Bvt+Ojo*JovWoK z{W2mM8>qAWooRK8ZuLPoxjk(o7nfA_JPWkX&?)rJTWc$nbPE}uF{r6+*zYHjzwrvb zt|o#hQ7~B8p?wsc?eal4dw0B4l#?@hpN~eEOTC?lW7DRmnHa`;vaC6tevWNlm!o;A zGK#tJ#szTlYArcqH^WQix0WnA|JCmfv@1jXukDS)Zy>$!J`v^o_`Q0W03Gq*T1681u%^SC6WCjhy*Bp#)v>h?s4o@Ppf;p z00c@04y?t0g`@zP(@Df^oEQ1D0VJMXY!y_@O>+xfZ1%p5=}=@EOnTOl&L3!ux*zGI^#@f_t|X)Q8!_wPe!EJX-(7z zg=jU848pj7(Kah?nu)?L9qU}Bw6fiIceYp3(#rL&F?ZhfFEO!rYdC6}N*-7-gJFx#4s3r)p6!Xt6*8NBG!T?M z^+Lr>rLHiPBSF}{esQ$enzQKo2QZNdpEL5LFIssm3oKXAblWlsB31BpPs>d@mqWJK zlxg-yp2^@CB;{KMAzDQGlV8cHX~HG?DAcq`kTgnpEy{U+PCwxs2FkcUO7&2 zxknMKsomw@O`VZ@NGS^7Mgnlz{68F_P{|YmH9VL=!$vyQqo7DV2ega*Mcg1-4^{sc z53@*|sxHldfE^)VbP>1?_(HOhY#;~0U?`pS7?Z*<9v&tx90iYn>8z%dA(XTQmUwKK zHY!gul9pdHS}LEypcxI9MziEokVYK&W2jw22JrTmU(=hiaP6DC^#M`1KnNl{zqAF4 z1C}gk0M7sYdAtN}b4y*mF@G@=R{{5*ZZm|h0AY43;Oo)J#SdH!JWi_9`BUZV)5*p6 zcmq7n5TU;c#n-Eoi|;4{ockG$)2#yN5c7xT>sJ8+d>(`;H9J2HU(X6)=)Z#bhq|3c zoLk>cV=@!VeiQK@YFAMA++s!muLr!dxpwYH-7^xN)Y3DgjUdEq9`NVK&ir{IaCVsO45T~9beSKJKVJlZjNb#CrqIl3GaW(#G}pYD4#G@q|F0pY yrjKB2C*R(`yOto*0-yo>JfxFbJJ;^aE`}dT(8HWjqGEi|MZgCQ5Tf-*U-=(W@ov!o literal 0 HcmV?d00001 diff --git a/jarslink-inject/src/test/resources/jarslink-module-b-1.0.0.jar b/jarslink-inject/src/test/resources/jarslink-module-b-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..78eba1e96f0e8ba4414f085aa2e1b56f2732f8af GIT binary patch literal 3900 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 F<-af$YOnwR literal 0 HcmV?d00001 diff --git a/jarslink-module-a/pom.xml b/jarslink-module-a/pom.xml new file mode 100644 index 0000000..bf977d7 --- /dev/null +++ b/jarslink-module-a/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + com.alipay.jarslink + jarslink-module-a + 1.0.0 + + + + 1.6 + + + + + com.alipay.jarslink.support + jarslink-inject + 1.0.0.20180403 + + + com.alipay.jarslink + jarslink-api + 1.7.0.20180401 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + ${java.version} + ${java.version} + UTF-8 + + + + + \ No newline at end of file diff --git a/jarslink-module-a/src/main/java/com/alipay/jarslink/demo/annotation/AAction.java b/jarslink-module-a/src/main/java/com/alipay/jarslink/demo/annotation/AAction.java new file mode 100644 index 0000000..74a14da --- /dev/null +++ b/jarslink-module-a/src/main/java/com/alipay/jarslink/demo/annotation/AAction.java @@ -0,0 +1,21 @@ +package com.alipay.jarslink.demo.annotation; + +import com.alipay.jarslink.api.Action; +import org.springframework.stereotype.Component; + +/** + * @author joe + * @version 2018.04.04 14:44 + */ +@Component +public class AAction implements Action { + @Override + public String execute(String actionRequest) { + return "a-" + actionRequest; + } + + @Override + public String getActionName() { + return "action-a"; + } +} diff --git a/jarslink-module-a/src/main/java/com/alipay/jarslink/demo/annotation/ActionProxy.java b/jarslink-module-a/src/main/java/com/alipay/jarslink/demo/annotation/ActionProxy.java new file mode 100644 index 0000000..343d27a --- /dev/null +++ b/jarslink-module-a/src/main/java/com/alipay/jarslink/demo/annotation/ActionProxy.java @@ -0,0 +1,27 @@ +package com.alipay.jarslink.demo.annotation; + +import com.alipay.jarslink.api.Action; +import com.alipay.jarslink.support.annotation.ActionReference; +import org.springframework.stereotype.Component; + +/** + * action注入测试使用 + * + * @author joe + * @version 2018.04.04 14:42 + */ +@Component +public class ActionProxy implements Action { + @ActionReference(moduleName = "demo-b", version = "1.0", name = "action-b") + private Action bAction; + + @Override + public String execute(String actionRequest) { + return bAction.execute(actionRequest); + } + + @Override + public String getActionName() { + return "proxy-" + bAction.getActionName(); + } +} diff --git a/jarslink-module-b/pom.xml b/jarslink-module-b/pom.xml new file mode 100644 index 0000000..420c468 --- /dev/null +++ b/jarslink-module-b/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.alipay.jarslink + jarslink-module-b + 1.0.0 + + + 1.6 + + + + + com.alipay.jarslink.support + jarslink-inject + 1.0.0.20180403 + + + com.alipay.jarslink + jarslink-api + 1.7.0.20180401 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + ${java.version} + ${java.version} + UTF-8 + + + + + \ No newline at end of file diff --git a/jarslink-module-b/src/main/java/com/alipay/jarslink/demo/annotation/ActionProxy.java b/jarslink-module-b/src/main/java/com/alipay/jarslink/demo/annotation/ActionProxy.java new file mode 100644 index 0000000..80d89e3 --- /dev/null +++ b/jarslink-module-b/src/main/java/com/alipay/jarslink/demo/annotation/ActionProxy.java @@ -0,0 +1,27 @@ +package com.alipay.jarslink.demo.annotation; + +import com.alipay.jarslink.api.Action; +import com.alipay.jarslink.support.annotation.ActionReference; +import org.springframework.stereotype.Component; + +/** + * 注入其他模块的action + * + * @author joe + * @version 2018.04.04 14:40 + */ +@Component +public class ActionProxy implements Action{ + @ActionReference(moduleName = "demo-a" , version = "1.0" , name = "action-a") + private Action aAction; + + @Override + public String execute(String actionRequest) { + return aAction.execute(actionRequest); + } + + @Override + public String getActionName() { + return "proxy-" + aAction.getActionName(); + } +} diff --git a/jarslink-module-b/src/main/java/com/alipay/jarslink/demo/annotation/BAction.java b/jarslink-module-b/src/main/java/com/alipay/jarslink/demo/annotation/BAction.java new file mode 100644 index 0000000..a02c419 --- /dev/null +++ b/jarslink-module-b/src/main/java/com/alipay/jarslink/demo/annotation/BAction.java @@ -0,0 +1,21 @@ +package com.alipay.jarslink.demo.annotation; + +import com.alipay.jarslink.api.Action; +import org.springframework.stereotype.Component; + +/** + * @author joe + * @version 2018.04.04 14:39 + */ +@Component +public class BAction implements Action{ + @Override + public String execute(String actionRequest) { + return "b-" + actionRequest; + } + + @Override + public String getActionName() { + return "action-b"; + } +} From 52226d23b5cecee989ba991f2a46fa2d6b30f80f Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Sun, 8 Apr 2018 10:56:47 +0800 Subject: [PATCH 21/24] =?UTF-8?q?=E5=B0=86=E6=B5=8B=E8=AF=95=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E6=8B=A6=E6=88=AA=E5=AE=9E=E7=8E=B0=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E5=88=B0=E4=B8=BB=E5=8C=85=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alipay/jarslink/support/ApplicationContextAwareImpl.java | 2 ++ 1 file changed, 2 insertions(+) rename jarslink-inject/src/{test => main}/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java (97%) diff --git a/jarslink-inject/src/test/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java b/jarslink-inject/src/main/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java similarity index 97% rename from jarslink-inject/src/test/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java rename to jarslink-inject/src/main/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java index fe77bdf..10c2888 100644 --- a/jarslink-inject/src/test/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java +++ b/jarslink-inject/src/main/java/com/alipay/jarslink/support/ApplicationContextAwareImpl.java @@ -9,6 +9,8 @@ import org.springframework.context.ConfigurableApplicationContext; /** + * 开启模块间调用的拦截 + * * @author joe * @version 2018.04.04 14:54 */ From 9311f61fe094c9bd8b361a5f3e864c23388edf4b Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Tue, 10 Apr 2018 13:37:35 +0800 Subject: [PATCH 22/24] =?UTF-8?q?=E5=88=A0=E9=99=A4bin=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index c47c747..8051e01 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,4 @@ /.classpath /.idea /.DS_Store -*.iml -/bin/ \ No newline at end of file +*.iml \ No newline at end of file From 184f96d162e357e391071ac283270b3a0db4d584 Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Tue, 10 Apr 2018 13:38:39 +0800 Subject: [PATCH 23/24] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E9=94=AE?= =?UTF-8?q?=E7=94=9F=E6=88=90module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/create-project.bat | 54 ++++++++++++++++++++++++++++ bin/create-project.sh | 57 ++++++++++++++++++++++++++++++ bin/template/project-template.tar | Bin 0 -> 40960 bytes 3 files changed, 111 insertions(+) create mode 100644 bin/create-project.bat create mode 100644 bin/create-project.sh create mode 100644 bin/template/project-template.tar diff --git a/bin/create-project.bat b/bin/create-project.bat new file mode 100644 index 0000000..1ed1a13 --- /dev/null +++ b/bin/create-project.bat @@ -0,0 +1,54 @@ +@echo off +echo -------------------------------------------- +echo Create Titan Module Batch +for /f "tokens=2 delims==" %%a in ('wmic path win32_operatingsystem get LocalDateTime /value') do ( + set t=%%a +) +set Today=%t:~0,4%-%t:~4,2%-%t:~6,2% +echo @version 1.0.%Today% +echo @author Administrator +echo -------------------------------------------- +set /p systemName=Please insert your Titan Module English name +echo -------------------------------------------- +echo Titan Module creatingPlease wait... +echo -------------------------------------------- +md %systemName%\src\main\java\com\mybank\bkcommon\collector\%systemName%\collector +md %systemName%\src\main\java\com\mybank\bkcommon\collector\%systemName%\model +md %systemName%\src\main\resources\META-INF\spring +md %systemName%\src\main\resources\view +md %systemName%\src\test\java\com\mybank\bkcommon\collector\%systemName% +md %systemName%\src\test\resources\ +copy project-template\helloworld.vm %systemName%\src\main\resources\view\helloworld.vm +copy project-template\HelloWorld.java %systemName%\src\main\java\com\mybank\bkcommon\collector\%systemName%\model\HelloWorld.java +copy project-template\HelloWorldCollector.java %systemName%\src\main\java\com\mybank\bkcommon\collector\%systemName%\collector\HelloWorldCollector.java +copy project-template\pom-template.xml %systemName%\pom.xml +copy project-template\integration.xml %systemName%\src\main\resources\META-INF\spring\integration.xml +copy project-template\QuickStarter-template.java %systemName%\src\test\java\com\mybank\bkcommon\collector\%systemName%\QuickStarter.java +copy project-template\integration-test.xml %systemName%\src\test\resources\integration-test.xml +copy project-template\spring-template.xml %systemName%\src\main\resources\META-INF\spring\%systemName%.xml +copy project-template\log4j-template.xml %systemName%\src\test\resources\log4j.xml +copy project-template\log4j-main-template.xml %systemName%\src\main\resources\log4j.xml +setlocal Enabledelayedexpansion +call:changePath %systemName%\src\test\java\com\mybank\bkcommon\collector\%systemName%\QuickStarter.java +call:changePath %systemName%\pom.xml +call:changePath %systemName%\src\test\resources\integration-test.xml +call:changePath %systemName%\src\main\resources\META-INF\spring\%systemName%.xml +call:changePath %systemName%\src\main\java\com\mybank\bkcommon\collector\%systemName%\model\HelloWorld.java +call:changePath %systemName%\src\main\java\com\mybank\bkcommon\collector\%systemName%\collector\HelloWorldCollector.java +call:changePath %systemName%\src\main\resources\log4j.xml +endlocal +echo "Create Titan Module %systemName% Finish" +pause + +:changePath +set pacStr=${package_name} +set proStr=${project_name} +set targetStr=%systemName% +for /f "tokens=* delims=" %%i in (%1) do ( + set var=%%i + set var=!var:%pacStr%=%targetStr%! + set var=!var:%proStr%=%targetStr%! + echo !var!>>$ +) +move $ %1 +goto:eof \ No newline at end of file diff --git a/bin/create-project.sh b/bin/create-project.sh new file mode 100644 index 0000000..4b6964b --- /dev/null +++ b/bin/create-project.sh @@ -0,0 +1,57 @@ +name=$1 + +if [ -z "$name" ]; then + echo "need name" + exit 2 +fi + +URL="https://private-alipayobjects.alipay.com/alipay-rmsdeploy-image/rmsportal/xJXQkCxicEVnAvkHWXgI.gz" +installer_file="project-template.tar.gz" + +function download { + echo "Downloading Titan project template: $URL" + curl -# $URL > $installer_file || exit +} + +function unzip { + echo "unzip $installer_file" + tar -zxvf $installer_file +} + +function createProject +{ + mkdir -p $name/src/main + mkdir -p $name/src/main/java/com/mybank/bkcommon/collector/$name + mkdir -p $name/src/main/java/com/mybank/bkcommon/collector/$name/collector + mkdir -p $name/src/main/java/com/mybank/bkcommon/collector/$name/model + mkdir -p $name/src/main/resources/META-INF/spring + mkdir -p $name/src/main/resources/view + + mkdir -p $name/src/test + mkdir -p $name/src/test/java/com/mybank/bkcommon/collector/$name/util + mkdir -p $name/src/test/resources/ + + cp project-template/helloworld.vm $name/src/main/resources/view/helloworld.vm + cp project-template/HelloWorld.java $name/src/main/java/com/mybank/bkcommon/collector/$name/model/HelloWorld.java + cp project-template/HelloWorldCollector.java $name/src/main/java/com/mybank/bkcommon/collector/$name/collector/HelloWorldCollector.java + cp project-template/pom-template.xml $name/pom.xml + cp project-template/integration.xml $name/src/main/resources/META-INF/spring/integration.xml + cp project-template/QuickStarter-template.java $name/src/test/java/com/mybank/bkcommon/collector/$name/QuickStarter.java + cp project-template/integration-test.xml $name/src/test/resources/integration-test.xml + cp project-template/spring-template.xml $name/src/main/resources/META-INF/spring/$name.xml + cp project-template/log4j-template.xml $name/src/test/resources/log4j.xml + cp project-template/log4j-main-template.xml $name/src/main/resources/log4j.xml + + sed -i '' 's/${package_name}/'$name'/g' $name/src/test/java/com/mybank/bkcommon/collector/$name/QuickStarter.java + sed -i '' 's/${project_name}/'$name'/g' $name/pom.xml + sed -i '' 's/${project_name}/'$name'/g' $name/src/test/resources/integration-test.xml + sed -i '' 's/${project_name}/'$name'/g' $name/src/main/resources/META-INF/spring/$name.xml + sed -i '' 's/${package_name}/'$name'/g' $name/src/main/java/com/mybank/bkcommon/collector/$name/model/HelloWorld.java + sed -i '' 's/${package_name}/'$name'/g' $name/src/main/java/com/mybank/bkcommon/collector/$name/collector/HelloWorldCollector.java + sed -i '' 's/${project_name}/'$name'/g' $name/src/main/resources/log4j.xml + echo "Create Titan Module $name Finish" +} + +download +unzip +createProject \ No newline at end of file diff --git a/bin/template/project-template.tar b/bin/template/project-template.tar new file mode 100644 index 0000000000000000000000000000000000000000..025e4861e0ce321cd03ba742708f9e6fe77f5fb5 GIT binary patch literal 40960 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 Dkf@Xw literal 0 HcmV?d00001 From 7bead3a5c01646fea59e299d0608704ccac85abd Mon Sep 17 00:00:00 2001 From: joe <1213812243@qq.com> Date: Thu, 12 Apr 2018 11:29:04 +0800 Subject: [PATCH 24/24] =?UTF-8?q?=E6=9B=B4=E6=94=B9maven=20plugin=EF=BC=88?= =?UTF-8?q?=E5=B0=86GPG=E6=8F=92=E4=BB=B6=E7=A7=BB=E5=85=A5profile?= =?UTF-8?q?=E4=B8=AD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jarslink-api/pom.xml | 68 +++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/jarslink-api/pom.xml b/jarslink-api/pom.xml index 8ddb3a4..7b1b2cd 100644 --- a/jarslink-api/pom.xml +++ b/jarslink-api/pom.xml @@ -95,37 +95,10 @@ test - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.7 - true - - ossrh - https://oss.sonatype.org/ - true - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - + + org.codehaus.mojo versions-maven-plugin @@ -255,6 +228,7 @@ + ossrh @@ -266,7 +240,43 @@ https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + deploy + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + +