簡體   English   中英

使用Spring在OSGi中使用范圍原型創建對象的不同實例

[英]Creating a different instance of an Object with scope prototype in OSGi using Spring

這是一個復雜的問題,因此我將盡力解釋。 我將三個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代碼片段,用於從安全捆綁包中獲取安全處理程序。 安全捆綁包中的此處理程序作為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方法時,捆綁包將傳遞該領域。

SpringsecurityHandler具有一個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配置中的不同捆綁中傳遞了不同的領域,但是該領域總是從第一個啟動的捆綁中開始,並且無法正常工作。

有人知道哪里可能出問題嗎?

問題是您從beanFactory獲得了單個“ securityHandler”。 因此,只有一個共享實例。 在createSecurityHandler內部,您應該創建一個新對象並返回它。

我能夠弄清楚為什么跨應用程序共享同一實例的問題。 我所有的捆綁包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 而且它無法在同一端口上處理不同的處理程序。 如果我將端口更改為全部不同,則一切正常。 但這不是我的解決方案。 解決方案是使所有捆綁包都使用一個領域。

AFAIR這里的問題更多是spring進行代理的方式。 原因是為服務引用而非服務完成了代理。 您可能需要正確配置它才能使用正確的代理。

我認為類似以下內容可能會有所幫助:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM