Domanda

Diciamo che ho una classe nella mia app web chiamata class " Foo " ;. Ha un metodo initialise () che viene chiamato quando il bean viene creato usando Spring. Il metodo initialise () quindi tenta di caricare un servizio esterno e assegnarlo a un campo. Se non è stato possibile contattare il servizio, il campo verrà impostato su null.

private Service service;

public void initialise() {
    // load external service
    // set field to the loaded service if contacted
    // set to field to null if service could not be contacted
}

Quando qualcuno chiama il metodo get () sulla classe " Foo " il servizio verrà richiamato se è stato avviato nel metodo initialise (). Se il campo per il servizio è nullo, voglio provare a caricare il servizio esterno.

public String get() {
    if (service == null) {
        // try and load the service again
    }
    // perform operation on the service is service is not null
}

È possibile che io abbia problemi di sincronizzazione se dovessi fare qualcosa del genere?

È stato utile?

Soluzione

La risposta di

?? toolkit è corretta. Per risolvere il problema, basta dichiarare il metodo initialise () di Foo come sincronizzato. Potresti refactificare Foo come:

private Service service;

public synchronized void initialise() {
    if (service == null) {
        // load external service
        // set field to the loaded service if contacted
    }
}

public String get() {
    if (service == null) {            
        initialise(); // try and load the service again
    }
    // perform operation on the service is service is not null
}

Altri suggerimenti

Sì, avrai un problema di sincronizzazione.

Supponiamo che tu abbia un servlet singolo:

public class FooServlet extends HttpServlet {

    private MyBean myBean;

    public void init() {
        myBean = (MyBean) WebApplicationContextUtils.
            getRequiredWebApplicationContext(getServletContext()).getBean("myBean");
    }

    public void doGet(HttpRequest request, HttpResponse response) {
        String string = myBean.get();
        ....
    }

}

class MyBean {
    public String get() {
        if (service == null) {
            // try and load the service again
        }
        // perform operation on the service is service is not null
    }
}

E la definizione del tuo bean è simile a:

<bean id="myBean" class="com.foo.MyBean" init-method="initialise" />

Il problema è che l'istanza del servlet è utilizzata da più thread di richiesta. Pertanto, il blocco di codice protetto da service == null può essere inserito da più thread.

La migliore soluzione (evitando il doppio controllo, ecc.) è:

class MyBean {
    public synchronized String get() {
        if (service == null) {
            // try and load the service again
        }
        // perform operation on the service is service is not null
    }
}

Spero che abbia senso. In caso contrario rilascia un commento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top