moduleLoader實際上就是模塊的“加載器”
我們從load方法開始
public Module load(ModuleConfig moduleConfig) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Loading module: {}", moduleConfig);
}
List<String> tempFileJarURLs = moduleConfig.getModuleUrlPath();
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Local jars: {}", tempFileJarURLs);
}
ConfigurableApplicationContext moduleApplicationContext = loadModuleApplication(moduleConfig, tempFileJarURLs);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Loading module complete:{}", moduleConfig);
}
return new SpringModule(moduleConfig, moduleConfig.getVersion(), moduleConfig.getName(),
moduleApplicationContext);
}
我們可以看到moduleLoader首先呼叫了loadModuleApplication方法,下面我們繼續看此方法
private ConfigurableApplicationContext loadModuleApplication(ModuleConfig moduleConfig, List<String>
tempFileJarURLs) {
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
//獲取模塊的ClassLoader
ClassLoader moduleClassLoader = new ModuleClassLoader(moduleConfig.getModuleUrl(), applicationContext
.getClassLoader(), getOverridePackages(moduleConfig));
try {
//把當前執行緒的ClassLoader切換成模塊的
Thread.currentThread().setContextClassLoader(moduleClassLoader);
ConfigurableApplicationContext context;
Properties properties = getProperties(moduleConfig);
Set<String> scanBase = moduleConfig.getScanPackages();
//注解方式加載bean
if (!scanBase.isEmpty()) {
ModuleAnnotationApplicationContext annotationConfigApplicationContext = new
ModuleAnnotationApplicationContext(properties);
annotationConfigApplicationContext.scan(scanBase.toArray(new String[0]));
context = annotationConfigApplicationContext;
} else {
//XML方式加載bean
ModuleXmlApplicationContext moduleApplicationContext = new ModuleXmlApplicationContext();
moduleApplicationContext.setProperties(properties);
moduleApplicationContext.setConfigLocations(findSpringConfigs(tempFileJarURLs, moduleClassLoader,
getExclusionConfigeNameList(properties)));
context = moduleApplicationContext;
}
context.setParent(applicationContext);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("module {}:{} allow current process to override bean in module", moduleConfig.getName(),
moduleConfig.getVersion());
}
((DefaultResourceLoader) context).setClassLoader(moduleClassLoader);
context.refresh();
return context;
} catch (Throwable e) {
CachedIntrospectionResults.clearClassLoader(moduleClassLoader);
throw Throwables.propagate(e);
} finally {
//還原當前執行緒的ClassLoader
Thread.currentThread().setContextClassLoader(currentClassLoader);
}
}
上面這段代碼可以說是jarslink的核心部分,此方法初始化了模塊自己的ClassLoader,初始化Spring Application Context,同時要設定當前執行緒背景關系的ClassLoader為模塊的ClassLoader,這樣就保證了實體隔離以及類隔離,
初始化背景關系的時候,jarslink只能采用注解加載或者xml方式加載,不過在實際工程中,我們可以使用@ImportResource等注解引入我們的xml,值得注意的是,springboot中使用的yml以及propertise方式初始化在jarslink中是無法使用的,需要修改為bean加載或者xml檔案加載,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/248545.html
標籤:其他
下一篇:RSA演算法密鑰長度的選擇
