2014-09-23 17 views
6

Possiedo una classe di registrazione che utilizza un servizio. Ogni volta che viene creato un nuovo logger, prevedo di avere accesso al servizio di registrazione con scope singleton.Il bean avviato automaticamente alla primavera provoca un puntatore nullo

I autowire il servizio di registrazione nel registro tuttavia, viene restituita un'eccezione di puntatore nullo. Ho provato un paio di soluzioni:

  1. definire manualmente il fagiolo nel contesto applicativo,
  2. Cercando di ottenere il logger da primavera gestito, ma che appena portato a più problemi.

Sto cercando di farlo funzionare nei miei test di junit, e specificherò il file di contesto per utilizzare un contesto di applicazione diverso. Tuttavia, anche se mantenuto identico, non risolve il problema.

Si prega di trovare codice qui sotto:

Il seguente è un estratto dal contesto dell'applicazione.

<context:component-scan base-package="com.platform"/> 
<bean id="asyncLoggingService" class="com.platform.services.AsyncLoggingServiceImplementation" scope="prototype"/> 

Quanto segue è la classe Logger.

package com.platform.utils; 


import com.platform.services.AsyncLoggingService; 
import org.joda.time.DateTime; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 

public class OurLogger 
{ 

    private static Logger logger; 

    @Autowired 
    private AsyncLoggingervice asyncLoggingService; 

    public OurLogger(Class Clazz) 
    { 
    logger = LoggerFactory.getLogger(Clazz); 
    } 


    public void trace(TraceableObject object, String message) 
    { 
    //Do nothing yet 
    } 

}

ho poi fare uso della Logger in un altro servizio per effettuare il login cosa sta succedendo. (Il motivo per cui sto scrivendo un altro logger è quello di utilizzare un server RabbitMQ) Nel servizio istanzio una nuova istanza del Logger e quindi la utilizzo di conseguenza.

@Service 
public class AsyncAccountServiceImplementation implements AsyncAccountService 
{ 
    private static final String GATEWAY_IP_BLOCK = "1"; 

    private static OurLogger logger = new  OurLogger(AsyncAccountServiceImplementation.class); 

... 
} 

Il puntatore nullo verifica nel OurLogger quando provo a chiamare qualsiasi metodo sul asyncLoggingService.

Quindi sto provando a testare lo AsyncAccountService utilizzando JUnit. Mi assicuro di aggiungere il diverso contesto applicativo, ma sembra ancora risultare nell'eccezione del puntatore nullo.

Se hai bisogno di ulteriori informazioni per favore fammi sapere. Ho visto modi per risolvere questo problema, ma non sembrano funzionare, quindi forse ho fatto un errore da qualche parte o non sto capendo tutto questo abbastanza correttamente.

+1

Come dovrebbe autowire a primavera un'istanza di cui non è a conoscenza. Stai creando tu stesso delle nuove istanze, mentre dovresti usare quella gestita dalla primavera. –

+0

Per quanto ne so (e, per favore, correggimi se ho torto come sono probabilmente), il bean viene specificato nel contesto dell'applicazione e quindi utilizzato (con lo stesso nome) nell'istanza OurLogger. L'unica area grigia che vedo è la creazione della nuova istanza di OurLogger, ma sicuramente deve essere ok usare un servizio autowired all'interno di un'istanza di un oggetto come questo. Grazie per il tuo commento finora. – robinjohnobrien

+1

No, non lo è ... Funzionerà solo con bean definiti e gestiti in primavera. Non appena farai un "nuovo OurLogger", non succederà nulla. A meno che non si usi AspectJ combinato con '@ Configurable'. –

risposta

8

Quando si crea un oggetto nuovo, autowire \ iniettare non funzionano ...

Vai a questa link e questo link per qualche soluzione alternativa.

Ad ogni modo se si immette un logger, suggerisco di rispondere a un altro argomento con this.

+0

Grazie, credo che il tuo lavoro funzionerà ma, per quanto ne so, è considerata una cattiva pratica prendere il bean direttamente dal contesto in quel modo. http://stackoverflow.com/questions/812415/why-is-springs-applicationcontext-getbean-considered-bad – robinjohnobrien

+0

Non è una cattiva pratica, è solo un modo diverso per risolvere un problema :) ma sono lati diversi della stessa cosa :) Comunque hai considerato il logger inietti come ti suggerisco? – Xstian

1

All'interno del vostro contesto di applicazione è necessario fare riferimento il vostro Logger:

<context:component-scan base-package="com.platform"/> 
<bean id="asyncLoggingService" class="com.platform.services.AsyncLoggingServiceImplementation" scope="prototype"/> 
<bean id="ourLogger" class="com.platform.utils.OurLogger"/> 

Poi si' per iniettarlo nel tuo servizio:

@Service 
public class AsyncAccountServiceImplementation implements AsyncAccountService 
{ 

private static final String GATEWAY_IP_BLOCK = "1"; 

@Autowired 
private OurLogger logger; 

} 
+0

Questo sarebbe il mio approccio, tuttavia, voglio che il logger istanzia il logger slf4j con un nome di classe.Quindi penso che il metodo @Configrable dovrebbe permettermi di seguire lo stesso metodo che descrivi qui. – robinjohnobrien

1

Utilizzare la struttura della molla Test dell'unità al posto del test JUnit per iniettare il fagiolo.

Può essere che ti aiuterà.

+1

Lo esaminerò grazie. – robinjohnobrien

4

Voglio solo aggiungere i miei 2 centesimi.

Una volta ho riscontrato lo stesso problema quando non ero abituato allo the life in the IoC world. Il campo @Autowired di uno dei miei bean è nullo in fase di runtime.

La causa principale è, invece di utilizzare il fagiolo creata automaticamente gestito dal container IoC Primavera (il cui @Autowired campo è indeed correttamente iniettato), io sono newing mia istanza di quella di fagioli e di utilizzarlo. Ovviamente il campo @Autowired di questo è nullo perché Spring non ha la possibilità di iniettarlo.

Problemi correlati