2016-09-19 311 views
0

在spring應用程序的啓動時,我想掃描計算機上的路徑,找到jar文件並從其中的xml配置文件構建一個spring應用程序上下文。每一件事情都可以將jar文件添加到類路徑並創建一個ApplicationContext。但是我從新的上下文中找不到任何bean。所有需要的依賴關係都可以在計算機上的特定路徑(通過maven複製插件)的jar文件中獲得,這些依賴項可以在基本的spring項目中使用(例如spring依賴本身)。 的代碼是(在科特林語言):動態加載spring xml配置

var loader = URLClassLoader(arrayOf(entry.toFile().toURL()), Thread.currentThread().contextClassLoader) 
... 
val context = ClassPathXmlApplicationContext("classpath*:/$name")//name is xml file. I'm sure the address in classpath is right. context is not creating when the address in wrong. for example: classpath://$name 
val services = context.getBeanNamesForType(IService::class.java)//services is empty 

我已經嘗試了許多其他的方式來加載XML,但他們都不是成功的。例如:

val beans = DefaultListableBeanFactory(applicationContext) 
val reader = XmlBeanDefinitionReader(beans) 
reader.beanClassLoader = loader 
reader.resourceLoader = resourceLoader 
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD) 
jarFile.getInputStream(jarEntry).use { 
    reader.loadBeanDefinitions(EncodedResource(InputStreamResource(it))) 
} 
beans.preInstantiateSingletons() 

jar文件中的XML看起來是這樣的:

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.0.xsd 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
<import resource="classpath*:/xxx-logic-context.xml"/> 
<context:annotation-config/> 
<context:component-scan base-package="aa.bbb.ccc.server"/> 
</beans> 

這真的很有趣:當我定義,而不是使用包scaning功能定期豆類,我可以在幾分拿到豆代碼

+0

'context:component-scan'使用與URLClassLoader不兼容的MAGIC。沒有運氣。 – talex

+0

@talex,但我已經在普通的春季啓動應用程序或簡單的彈簧應用程序中使用了與ClassPathXmlApplicationContext完全相同的xml(具有包掃描和日程安排功能)。唯一不同的是添加類加載器。 Spring如何將常規應用程序中的導入添加到其他XML中?它必須有一個解決方案。 –

+1

不幸的是。有了MAGIC,它經常發生。 rison的意思是Java沒有函數枚舉類和子包並且'component-scan'依賴於這個特性。當前的實現使用把'jar'文件作爲簡單的'zip'並讀取類列表的技巧。但它只能使用默認的類加載器。從理論上講,可以爲其他ClassLoader實現此功能,但沒有人做到這一點。 – talex

回答

1

來自@talex的偉大答案引導了我。我通過設置當前類加載器來修復它:

val loader = URLClassLoader(arrayOf(entry.toFile().toURL()), Thread.currentThread().contextClassLoader) 
Thread.currentThread().contextClassLoader = loader