2015-11-10 10 views
7

Sto lavorando a un'utilità per supportare l'iniezione dipendente dal contesto, ovvero ciò che viene iniettato può ora dipendere anche da dove viene iniettato. L'iniezione di un logger è un'applicazione comune di questa tecnica. Finora, ho implementato con successo questo per HK2 e Guice e con alcune limitazioni per Dagger. Per risolvere questo per Spring, sto usando un BeanFactoryPostProcessor che registra un AutowireCandidateResolver. Tuttavia, per ottenere la semantica desiderata, ho bisogno di conoscere il tipo di oggetto target effettivo, che può essere diverso dal tipo che dichiara il punto di iniezione. Ad esempio: devono essere iniettati con un registratore per SubClass, non con un registratore per BaseClassAccesso a "contenente la classe" da DependencyDescriptor

class BaseClass { 
    @Inject Logger logger; 
} 

class SubClass extends BaseClass { 
} 

istanze di sottoclasse. DependencyDescriptor contiene queste informazioni nel campo containClass, ma sfortunatamente queste informazioni non sono esposte tramite l'API.

Domanda 1: Esiste un motivo architettonico per cui questa informazione non è esposta o potrebbe essere aggiunta a tale API DependencyDescriptor?

Domanda 2: Nel frattempo, qual è il modo migliore per aggirare questa limitazione? L'accesso al campo interno tramite l'API di Reflection è brutto e viola l'incapsulamento. L'altra alternativa è quella di iniettare prima l'istanza sbagliata (cioè Logger for BaseClass) e poi correggerla successivamente con un BeanPostProcessor, ma vorrei rifare manualmente un sacco di lavoro (cioè rielaborare praticamente l'intera gestione dell'iniezione).

+0

http://stackoverflow.com/questions/3038179/spring-constructor-injection-of-slf4j-logger-how-to-get-injection-target-class –

risposta

1

Ora è abbastanza sicuro qual è il motivo della severità dell'API DependencyDescriptor. Ma il punto di partenza per te non dovrebbe essere il BeanFactoryPostProcessor ma dovresti dare un'occhiata a BeanPostProcessor e in particolare a AutowiredAnnotationBeanPostProcessor che autowires campi annotati, metodi setter e metodi di configurazione arbitrari basati sulle annotazioni @Autowired, @Value e @Inject. Come ho capito questo è quello che vuoi fare. Questa classe è responsabile della creazione di DependencyDescriptor. Quindi, può essere quello che devi fare è:

  1. Creare un costume DependencyDescriptor (basta estenderla con l'accesso del pubblico a "classe contenente")
  2. Creare un costume AutowiredAnnotationBeanPostProcessor che farà stesse cose di AutowiredAnnotationBeanPostProcessor ma invece di creare l'istanza di DependencyDescriptor creerà quello dal punto 1.
  3. creare un costume AutowireCandidateResolver che sarà solo gettare la DependencyDescriptor a quella che avete creato (quindi può pubblicamente di accesso "contenente classe" proprietà.)
+0

Grazie, Babl. Buona risposta! Ho completamente dimenticato di controllare StackOverflow per vedere se qualcuno avesse risposto. La soluzione che ho trovato non è identica a ciò che hai descritto, ma in qualche modo simile: https://github.com/raner/loginject/blob/master/loginject/loginject-spring/src/main/java/org/loginject/ SpringLogInjectionService.java – user1932890

Problemi correlati