【问题标题】:Creating a different instance of an Object with scope prototype in OSGi using Spring使用 Spring 在 OSGi 中创建具有范围原型的对象的不同实例
【发布时间】:2012-09-13 23:19:33
【问题描述】:

这是一个复杂的问题,所以我会尽可能清楚地解释它。我将三个OSGi 捆绑包ABC 部署到Apache Karaf。我还有一个安全包,供ABC 包使用。

每个 ABC 包都包含以下内容:

<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>

Spring 代码 sn-p 从安全包中获取安全处理程序。安全包中的此处理程序公开为OSGi 服务并在安全包中创建,如下所示:

<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"/>

BasicAuthFactoryHandlerImpl#createSecurityHandler(String realm) 用于为每个捆绑包创建不同的安全处理程序实例。当Spring MethodInvokingFactoryBean 调用createSecurityHandler 方法时,该领域由bundle 传递,如上面的代码所示。

securityHandler Spring bean 有一个 scope 原型,在这种情况下,当每次调用 getBean 方法时都会返回一个新创建的对象。

我为安全处理程序设置的领域是这样的:

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;
    }
}

每个包的处理程序被创建,一切都很好。但问题是所有捆绑包的领域在某种程度上与从第一个启动捆绑包传递的领域相同。我确定我在不同捆绑包中的每个Spring 配置中传递了不同的领域,但领域始终来自第一个启动的捆绑包,并且无法正常工作。

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

【问题讨论】:

    标签: java spring jetty osgi apache-karaf


    【解决方案1】:

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

    【讨论】:

    • 我试过了,没用。仍然存在同样的问题。安全处理程序有一个范围原型,因此从 spring 文档中它应该返回一个对象的新实例。问题不存在。
    【解决方案2】:

    我能够弄清楚为什么同一个实例在应用程序之间共享的问题。我所有的捆绑包ABC,都使用了这个:

    <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。而且它无法处理同一端口上的不同处理程序。如果我将端口更改为完全不同,则一切正常。但这不是我的解决方案。解决方案是让所有捆绑包都使用一个领域。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2013-06-14
        • 1970-01-01
        • 1970-01-01
        • 2011-05-06
        • 2012-03-28
        • 2012-04-12
        • 2011-06-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多