Domanda

Quando inizi a scherzare con le cose di proxy automatico di Spring, spesso ti imbatti in questo comportamento come documentato:

  

Classi che implementano il   Interfaccia BeanPostProcessor sono   speciale, e quindi vengono trattati   diversamente dal contenitore. Tutti   BeanPostProcessors e loro direttamente   i bean referenziati verranno istanziati   all'avvio, come parte dello speciale   fase di avvio di   ApplicationContext, quindi tutti quelli   I processori BeanPost saranno registrati   in modo ordinato - e applicato a   tutti gli altri fagioli. Dal momento che AOP   il proxy automatico è implementato come a   BeanPostProcessor stesso, no   BeanPostProcessors o direttamente   i fagioli referenziati sono idonei per   auto-proxy (e quindi non avrà   aspetti "intrecciati" in essi.

     

Per tale bean, dovresti vedere un   messaggio registro informazioni: "Fagiolo" non lo è   idoneo per essere elaborato da tutti   BeanPostProcessors (ad esempio: no   idoneo al proxy automatico) ".

In altre parole, se scrivo il mio BeanPostProcessor e quella classe fa riferimento direttamente ad altri bean nel contesto, i bean a cui si fa riferimento non saranno idonei al proxy automatico e un messaggio verrà registrato in tal senso.

Il mio problema è che rintracciare dove si trova quel riferimento diretto può essere molto difficile, dal momento che il "riferimento diretto" può infatti essere una catena di dipendenze transitive che finisce per contenere metà dei bean nel contesto dell'applicazione. All Spring ti dà quel singolo messaggio informativo, e non è davvero di grande aiuto, oltre a dirti quando un bean è stato catturato in questa rete di riferimenti.

Il processore BeanPost che sto sviluppando ha riferimenti diretti ad altri bean, ma è un insieme di riferimenti molto limitato. Nonostante ciò, praticamente ogni bean nel mio contesto viene quindi escluso dall'auto-proxy, secondo i messaggi di log, ma non riesco a vedere dove sta avvenendo tale dipendenza.

Qualcuno ha trovato un modo migliore per rintracciarlo?

È stato utile?

Soluzione 2

Solo per portare un po 'di chiusura a questa domanda, il crollo del grafico a oggetti non inizializzato è stato causato dal BeanPostProcessor usando @Autowired per ottenere le sue dipendenze e il meccanismo di autowire di fatto, ogni altra definizione di bean è stata inizializzata prima che il mio BeanPostProcessor avesse avuto la possibilità di avere voce in capitolo. La soluzione non è utilizzare l'autowiring per i tuoi BPP.

Altri suggerimenti

Segui questa ricetta:

  1. Apri BeanPostProcessorChecker nel tuo IDE (è una classe interna di AbstractApplicationContext )
  2. Imposta un punto di interruzione su if (logger.isInfoEnabled ()) { nel metodo postProcessAfterInitialization
  3. Esegui il tuo codice
  4. Quando raggiungi il punto di interruzione, cerca le chiamate a getBean (String, Class < T >) nella traccia dello stack.

    Una di queste chiamate proverà a creare un BeanPostProcessor . Quel fagiolo dovrebbe essere il colpevole.

Sfondo

Immagina questa situazione:

public class FooPP implements BeanPostProcessor {
    @Autowire
    private Config config;
}

Quando Spring deve creare config (poiché è una dipendenza di FooPP ), ha un problema: il contratto afferma che tutti i BeanPostProcessor deve essere applicato a ogni bean che viene creato. Ma quando Spring ha bisogno di config , c'è almeno un PP (ovvero FooPP ) che non è pronto per il servizio!

Questo peggiora quando si utilizza una classe @Configuration per definire questo bean:

@Configuration
public class BadSpringConfig {
     @Lazy @Bean public Config config() { return new Config(); }
     @Lazy @Bean public FooPP fooPP() { return new FooPP(); }
}

Ogni classe di configurazione è un bean. Ciò significa che per costruire un bean factory da BadSpringConfig , Spring deve applicare il post-processor fooPP ma per farlo, per prima cosa ha bisogno del bean factory ...

In questo esempio, è possibile interrompere una delle dipendenze cicliche. Puoi fare in modo che FooPP implementi BeanFactoryAware per fare in modo che Spring inietti BeanFactory nel post processore. In questo modo, non è necessario il collegamento automatico.

Più avanti nel codice, puoi chiedere pigramente il bean:

private LazyInit<Config> helper = new LazyInit<Config>() {

    @Override
    protected InjectionHelper computeValue() {
        return beanFactory.getBean( Config.class );
    }
};

@Override
public Object postProcessBeforeInitialization( Object bean, String beanName ) throws BeansException {
     String value = helper.get().getConfig(...);
}

( fonte per LazyInit )

Per interrompere il ciclo tra il bean factory e il post processor, è necessario configurare il post processor in un file di configurazione XML. Spring può leggerlo e costruire tutte le strutture senza essere confuso.

Non sono sicuro che sia di aiuto, ma Eclipse IDE di primavera visualizzazione grafica sembra che potrebbe essere utile per ordinare i riferimenti di bean ..

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