Pregunta

Digamos que tengo una clase en mi aplicación web llamada clase " Foo " Tiene un método initialise () que se llama cuando el bean se crea utilizando Spring. El método initialise () intenta cargar un servicio externo y asignarlo a un campo. Si no se pudo contactar con el servicio, el campo se establecerá en nulo.

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
}

Cuando alguien llama al método get () en la clase " Foo " el servicio se invocará si se inició en el método initialise (). Si el campo para el servicio es nulo, quiero intentar cargar el servicio externo.

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

¿Es posible que tenga problemas de sincronización si haría algo como esto?

¿Fue útil?

Solución

La respuesta de

toolkit es correcta. Para resolver el problema, simplemente declare que su método de inicialización () de Foo esté sincronizado. Podrías refactorizar a Foo como:

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
}

Otros consejos

Sí, tendrás un problema de sincronización.

Supongamos que tiene un solo servlet:

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

Y su definición de bean parece:

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

El problema es que su instancia de servlet es utilizada por varios subprocesos de solicitud. Por lo tanto, el bloque de código protegido por el servicio == nulo puede ser ingresado por múltiples hilos.

La mejor solución (evitar el doble control del bloqueo, etc.) es:

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

Espero que esto tenga sentido. Deja un comentario si no.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top