我正在创建一个非常简单的应用程序,我尝试使用osgi(apache felix)初始化一个spring bean。我设法用这样的代码读取我在包中包含的spring-beans.xml
文件:
ApplicationContext springContext = new GenericApplicationContext();
InputStream in = thisBundle.getEntry("/spring-beans.xml").openStream();
DefaultListableBeanFactory beans = new DefaultListableBeanFactory(springContext);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beans);
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
reader.loadBeanDefinitions(new InputStreamResource(in));
beans.preInstantiateSingletons();
in.close();
return springContext;
这是spring-beans.xml
的内容:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="crazyClass" class="foo.bar.osgi.SpringInstantiatedBean">
<property name="name" value="YES" />
</bean>
</beans>
SpringInstantiatedBean类只有一个prop(name)和一个getter / setter。如果我通过主类在本地运行它,这一切都很好,尽管定位spring-beans.xml文件的路径有点不同。但是,当我把这段代码放在felix上时,这就是我在Activator中得到的:
Jun 7, 2012 4:37:40 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from resource loaded through InputStream
Jun 7, 2012 4:37:41 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2778c490: defining beans [crazyClass]; root of factory hierarchy
org.osgi.framework.BundleException: Activator start error in bundle foo.bar.osgi.OSGIProject [91].
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2027)
at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)
at org.apache.felix.gogo.command.Basic.start(Basic.java:729)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:137)
at org.apache.felix.gogo.runtime.CommandProxy.execute(CommandProxy.java:82)
at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:477)
at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:403)
at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108)
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:183)
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:120)
at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:89)
at org.apache.felix.gogo.shell.Console.run(Console.java:62)
at org.apache.felix.gogo.shell.Shell.console(Shell.java:203)
at org.apache.felix.gogo.shell.Shell.gosh(Shell.java:128)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:137)
at org.apache.felix.gogo.runtime.CommandProxy.execute(CommandProxy.java:82)
at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:477)
at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:403)
at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108)
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:183)
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:120)
at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:89)
at org.apache.felix.gogo.shell.Activator.run(Activator.java:75)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [foo.bar.osgi.SpringInstantiatedBean] for bean with name 'crazyClass' defined in resource loaded through InputStream; nested exception is java.lang.ClassNotFoundException: foo.bar.osgi.SpringInstantiatedBean
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1262)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:576)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1331)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:897)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:566)
at foo.bar.osgi.Activator.readSpringConfigAndInitContext(Activator.java:54)
at foo.bar.osgi.Activator.start(Activator.java:29)
at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
... 32 more
Caused by: java.lang.ClassNotFoundException: foo.bar.osgi.SpringInstantiatedBean
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:257)
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:417)
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1283)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1254)
... 40 more
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [foo.bar.osgi.SpringInstantiatedBean] for bean with name 'crazyClass' defined in resource loaded through InputStream; nested exception is java.lang.ClassNotFoundException: foo.bar.osgi.SpringInstantiatedBean
完整的堆栈跟踪只是告诉我,在解析bean的那一刻,spring internals找不到我的bean类,这很奇怪,因为我可以在我的Activator中实例化它没有问题,就像那样:
SpringInitializedBean bean = new SpringInitializedBean();
这只表明它是一个类加载器问题,但是BeanFactory
的类加载器是否有可能无法访问我的类?如果是这样,我如何让它看到我的课程?另外,这里是我配置maven bundle插件的pom.xml
的摘录:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.2.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Activator>foo.bar.osgi.Activator</Bundle-Activator>
<Export-Package>foo.bar.osgi.osgi*</Export-Package>
<Private-Package>foo.bar.osgi*</Private-Package>
<Import-Package>*</Import-Package>
<Include-Resource>src/main/resources/spring-beans.xml</Include-Resource>
</instructions>
</configuration>
</plugin>
答案 0 :(得分:0)
您的问题似乎是Spring尝试使用Class.forName或类似方法加载bean。它假定该类在系统类加载器中可见。由于OSGi具有强大的类别分离以及每个包的单独类加载器,因此这种假设不正确。
BeanFactory在哪里?它是在OSGi框架的系统类路径中,还是打包为捆绑包本身? 如果它在一个包中,您可以尝试使用两个包的清单中的Import-Package:和Export-Package子句作为临时解决方案。
答案 1 :(得分:0)
试图弄清楚两件便宜的东西: