2013-07-23 2 views
6

Oggi, abbiamo trovato questo modello nel nostro codice:Trovare fagioli Singleton stateful

class Foo { 
    private List<String> errors; 

    public void addError(String error) { ... } 
    public List<String> getErrors(); 
} 

Mentre il codice sembra funzionare, questo è un bean Spring Singleton ed è iniettato in più punti indipendenti e consumatori di fagiolo supponiamo che ognuno abbia la propria lista di errori. Quindi questo introduce bug sottili.

La soluzione ovvia è quella di educare gli sviluppatori ad evitare questo tipo di errore, ma mi chiedevo se c'è uno strumento di analisi del codice statico o di runtime che può trovare questo tipo di bug.

Ad esempio, un postprocessore di bean può analizzare il bean prima che venga restituito e cercare campi privati ​​che non siano @Autowired.

+0

Possiamo usare @postConstruct per resettare quel campo privato? – sreeprasad

+0

@SREEPRASADGOVINDANKUTTY: Si potrebbe provare ma non funzionerebbe poiché '@ PostConstruct' verrebbe chiamato una sola volta quando si crea Foo. Non è possibile utilizzare '@ PostConstruct' nel bean A per reimpostare il campo poiché ciò cancellerebbe anche l'elenco per il bean B. –

+0

Anche se non è un modo molto pulito, è possibile provare l'APO di primavera, aggiungere dopo l'avviso e in tale metodo è possibile controllare questi campi. –

risposta

1

Dopo aver versato qualche più cervello (la nostra e di altri popoli) su questo, siamo arrivati ​​a questo approccio:

  1. Installare una BeanPostProcessor, che fa in modo che tutti i fagioli Singleton (cioè dove la portata del fagiolo definizione è Singleton) ha l'annotazione personalizzata @Stateless sul tipo di bean effettivo.

    Abbiamo scelto un'annotazione personalizzata invece di riutilizzare @Singleton poiché abbiamo bisogno anche di questa funzionalità altrove.

    Se l'annotazione è mancante, la fabbrica genera un errore.

  2. In un test di unità, si utilizza ClassPathScanningCandidateComponentProvider con un'annotazione personalizzata per individuare tutte le classi sul classpath. Possiamo quindi eseguire i test complessi e costosi per assicurarci che il bean non abbia uno stato che cambi dopo la configurazione iniziale (ad esempio dopo che è avvenuto l'autowiring).

Il secondo passo potrebbe diventare un po 'più facile se ci siamo spostati i campi autowired al costruttore, ma non ci piace metodi che prendono molti, molti argomenti. Sarebbe bello se Java o un IDE potesse generare builder dal codice bean. Dal momento che non è il caso, ci atteniamo ai campi e/o setter autowired.

0

È possibile creare un test JUnit per caricare la configurazione dell'app. Questo potrebbe combinare ListableBeanFactory da qui:

Can I dynamically create a List by scanning the beans in a spring configuration file?

con il controllo 'isSingleton' qui:

How to enforce a prototype scope of Spring beans

vale a dire l'elenco di tutti i fagioli nel contesto app, quindi controllare per vedere quali sono single.

Ciò consentirebbe di trovare tutti i bean singleton ... anche se non impedirebbe realmente il tuo caso di errore in cui qualcuno tratta uno di questi singleton come se non lo fosse.