Java 使用Spring在OSGi中创建具有范围原型的对象的不同实例

Java 使用Spring在OSGi中创建具有范围原型的对象的不同实例,java,spring,jetty,osgi,apache-karaf,Java,Spring,Jetty,Osgi,Apache Karaf,这是一个复杂的问题,所以我会尽可能清楚地解释它。我有三个OSGi捆绑包A,B,C部署到apachekaraf。我还有一个安全捆绑包,由a、B、C捆绑包使用 每个A、B和C捆绑包都包含以下内容: <osgi:reference id="basicAuthHandlerFactory" interface="com.groupgti.security.handler.basicauth.BasicAuthHandlerFactory"/> <bean id="securityHa

这是一个复杂的问题,所以我会尽可能清楚地解释它。我有三个
OSGi
捆绑包
A
B
C
部署到
apachekaraf
。我还有一个安全捆绑包,由
a
B
C
捆绑包使用

每个
A
B
C
捆绑包都包含以下内容:

<osgi:reference id="basicAuthHandlerFactory" interface="com.groupgti.security.handler.basicauth.BasicAuthHandlerFactory"/>

<bean id="securityHandler" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="basicAuthHandlerFactory"/>
    <property name="targetMethod" value="createSecurityHandler"/>
    <property name="arguments">
        <list>
            <value type="java.lang.String">A.realm</value> <!-- The realm is depending on a bundle, A.realm, B.realm, C.realm -->
        </list>
    </property>
</bean>
BasicAuthFactoryHandlerImpl#createSecurityHandler(字符串域)
用于为每个捆绑包创建不同的安全处理程序实例。当
Spring
MethodInvokingFactoryBean
调用
createSecurityHandler
方法时,领域由bundle传递,如上述代码所示

securityHandler
Spring
bean有一个
范围
原型,在这种情况下,当调用方法
getBean
时,应该返回一个新创建的对象

我为安全处理程序设置的领域如下:

<bean id="securityHandler" class="org.eclipse.jetty.security.ConstraintSecurityHandler" scope="prototype">
    <property name="authenticator">
        <bean class="org.eclipse.jetty.security.authentication.BasicAuthenticator"/>
    </property>
    <property name="constraintMappings">
        <list>
            <ref bean="constraintMapping"/>
        </list>
    </property>
    <property name="strict" value="false"/>
    <property name="identityService" ref="identityService"/>
</bean>

<bean id="basicAuthSecurityHandler" class="com.groupgti.security.handler.basicauth.BasicAuthFactoryHandlerImpl"/>
<osgi:service ref="basicAuthSecurityHandler" interface="com.groupgti.security.handler.basicauth.BasicAuthHandlerFactory"/>
public class BasicAuthFactoryHandlerImpl implements BeanFactoryAware, BasicAuthHandlerFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(BasicAuthFactoryHandlerImpl.class);

    private BeanFactory factory;

    @Override
    public ConstraintSecurityHandler createSecurityHandler(String realm) {
        ConstraintSecurityHandler handler = (ConstraintSecurityHandler) factory.getBean("securityHandler");
        handler.setUserRealm(realm);
        LOGGER.debug("Security handler created. Got realm: {}", realm);
        return handler;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.factory = beanFactory;
    }
}
创建每个包的处理程序后,一切正常。但问题是,所有bundle的领域在某种程度上都是从第一个启动的bundle传递的相同领域。我确信我在不同的bundle中的每个
Spring
配置中传递了不同的领域,但是领域总是从第一个启动的bundle开始,并且它不能正常工作


有人知道问题出在哪里吗?

问题是您从beanFactory获得了一个“securityHandler”。因此,只有一个共享实例。在createSecurityHandler中,您应该创建一个新对象并返回它

我能够找出为什么在应用程序之间共享同一实例的问题。我的所有捆绑包
A
B
C
,都使用了以下内容:

<httpj:engine-factory bus="cxf">
    <httpj:engine port="8020">
        <httpj:threadingParameters minThreads="5" maxThreads="15"/>
        <httpj:handlers>
            <ref bean="securityHandler"/>
            <ref bean="ipFilteringHandler"/>
        </httpj:handlers>
        <httpj:sessionSupport>true</httpj:sessionSupport>
    </httpj:engine>
</httpj:engine-factory>

真的

为了创建安全处理程序,Jetty使用了相同的端口
8020
。它无法在同一个端口上处理不同的处理程序。如果我将端口更改为完全不同,那么一切都正常。但这不是我的解决办法。解决方案是让一个领域供所有bundle使用。

AFAIR这里的问题更多的是spring代理的方式。原因代理是针对服务引用而不是服务执行的。您可能需要正确配置它以使用正确的代理

我认为下面的内容可能会有所帮助:

ServiceReference nativeReference = ((ServiceReferenceProxy)serviceReference).getTargetServiceReference() 

我试过了,没用。还是有同样的问题。安全处理程序有一个作用域原型,因此从spring文档中,它应该返回一个对象的新实例。问题不在那里。