2014-11-13 10 views
7

CDI ha la funzione di Specialization, e lo sto cercando nel mondo primaverile.@Specializza in primavera

Dettagli. In CDI, l'annotazione @Specializes consente di modificare il comportamento di un bean semplicemente sovrascrivendolo. Ciò è completamente trasparente per gli utenti di quel bean, ad es. Se avessimo

public class OneBean { 
    public String whoAmI() { return "OneBean"; } 
} 

@Specializes 
public class AnotherBean extends OneBean { 
    @Override 
    public String whoAmI() { return "AnotherBean"; } 
} 

potremmo

public class SomewhereElse { 
    @Inject 
    OneBean oneBean; // we know nothing of AnotherBean here! 

    public void guessWhosThere() { 
    return oneBean.whoAmI(); // yet it returns "AnotherBean" 
    } 
} 

Questo diventa molto utile non appena OneBean viene effettivamente utilizzato con e senza AnotherBean. Ad esempio, se OneBean è in one.jar e AnotherBean è in another.jar, è possibile modificare il comportamento del bean solo riconfigurando il classpath.

Domanda. Esiste qualcosa come la specializzazione anche in primavera?

sono riuscito a trovare solo la @Primary annotazione, che ha però una semantica diversa: @Primary non sostituisce un fagiolo, ma segna solo uno dei molteplici alternative come il primario uno. Soprattutto, come ho capito, non sono riuscito a costruire una gerarchia di eredità profonda come è possibile con @Specializes.

+1

Cosa ti impedisce di modificare la firma in 'classe pubblica astratta OneBean'? Concettualmente non è così ovvio, ma se capisco 'Specializes' correttamente, sembra che tu abbia la stessa funzionalità. – Floegipoky

+1

Sì, hai ragione: nell'esempio dato, potevo semplicemente rendere astratto 'OneBean'. Tuttavia, a quanto pare, non avrei nemmeno bisogno di '@ Specializza' in questo caso. L'annotazione diventa davvero utile non appena si usa effettivamente 'OneBean', ad esempio in' one.jar', e 'AnotherBean' potrebbe cambiarne il comportamento, ad esempio non appena' another.jar' (contenente 'AnotherBean') è nel classpath. – fxnn

risposta

1

Risposta breve Nella primavera 4, questo non è possibile. Periodo. Ancora, nel 2016, niente di simile è possibile con il modello obsoleto di iniezione a dipendenza di Spring.

1

Sembra che non ci siano annotazioni simili in primavera, ma è possibile raggiungerlo tramite @Qualifier.

Fagioli:

@Resource("oneBean") 
public class OneBean { 
    public String whoAmI() { return "OneBean"; } 
} 

@Resource("anotherBean") 
public class AnotherBean extends OneBean { 
    @Override 
    public String whoAmI() { return "AnotherBean"; } 
} 

SomewhereElse:

public class SomewhereElse { 
    @Autowired 
    @Qualifier("anotherBean") 
    OneBean oneBean; 

    public void guessWhosThere() { 
    return oneBean.whoAmI(); // returns "AnotherBean" 
    } 
} 

modificato.

Inoltre è possibile sviluppare la propria annotazione e utilizzarlo in BeanPostProcessor, un'occhiata a documenti di primavera here

O ancora meglio utilizzare CustomAutowireConfigurer, vedere here

+0

Non penso che questo sia ciò che l'OP sta cercando. Se 'YetAnotherBean' arriva, non farà quello che vuole. – Floegipoky

+0

Vero. Ho aggiunto un commento nell'esempio OP: 'SomewhereElse' sa * nothing * di' AnotherBean'. Con l'annotazione '@ Qualifier' suggerita qui, dovremmo dipendere da esso (non per tipo, ma per nome). – fxnn

+0

È necessario modificare tutti i punti di iniezione aggiungendo un qualificatore. Punto di specializzazione è quello di sostituire completamente un bean con un altro senza la necessità di modificare il codice corrente o informare altri sviluppatori di utilizzare qualche tipo di qualificatore speciale. –

0

Se assumiamo che:

public interface BeanInterface { 
    String whoAmI(); 
} 

@Named 
public class OneBean implements BeanInterface { 
    @Override 
    public String whoAmI() { return "OneBean"; } 
} 

@Named 
@Primary 
public class AnotherBean implements BeanInterface { 
    @Inject 
    OneBean oneBean; 

    @Override 
    public String whoAmI() { 
    String oneBeanId = oneBean.whoAmI(); 
    return "AnotherBean calling: " + oneBeanId; 
    } 
} 

potremmo, invece di estendere OneBean decoralo con qualche altro comportamento. La mancanza di questa soluzione è che ciascun metodo di BeanInterface deve essere implementato in AnotherBean e delegato al suo campo oneBean.

+0

Ora, se ho un '@Autowired BeanInterface someBean', ottengo' someBean.whoAmI(). Equals ("AnotherBean calling: OneBean") == true'? – fxnn

+0

Perché non ci provi? –