2016-02-29 18 views
8

Ci sono differenze tra intercettori e decoratori in Java? A rigor di termini, posso implementare le cose con i decoratori che non sono possibili con gli intercettori e viceversa?Differenza tra intercettori e decoratori

Tranne il problema che avrei dovuto esaminare il nome del metodo per aggiungere comportamento specifico metodo in un intercettore:

Interceptor:

@Nice 
@Interceptor 
public class NiceGreeterInterceptor { 
    @AroundInvoke 
    public Object decorate(InvocationContext ic) throws Exception { 
    Method method = ic.getMethod(); 
    String methodName = method.getName(); 
    Object result = ic.proceed(); 
    if (methodName.equals("greet")) { 
     return "NEW " + result; 
    } 
    } 
} 

Decorator:

@Decorator 
public class GreeterDecorator implements Greeter { 
    @Inject 
    @Any 
    @Delegate 
    private Greeter greeter; 

    @Override 
    public String greet() { 
    return "NEW " + greeter.greet(); 
    } 
} 

O è è legittimo dire che posso riprodurre tutto il comportamento dei decoratori con gli intercettori ma è più comodo usare i decoratori?

risposta

8

Una differenza sarebbe, come mostra il tuo esempio, con decoratore di solito scrivi 1 decoratore per 1 classe/interfaccia decorata.

Con gli intercettori, che fanno parte del concetto AOP, si scrive 1 intercettore per un gruppo di classi/metodi, ad es. intercetti tutti i metodi DAO e assicurati che una transazione sia aperta prima dell'invocazione e chiusa dopo di essa.

Un esempio di un intercettatore in AOP primavera, in primo luogo si dichiara una pointcut (cosa corrispondenti), qui di abbinare qualsiasi metodo della classe MyDao che inizia con inserto, ha argomenti e qualsiasi tipo di ritorno.

@Pointcut("execution(* com.example.dao.MyDao.insert*(..))") 
public void insertPointcut() { 
} 

Poi si dichiara un around advice che fa riferimento al pointcut

@Around(value = "com.example.SystemArchitecture.insertPointcut()") 
public void interceptMethod(ProceedingJoinPoint pjp) { 
     // do pre-work 
     Object retVal = pjp.proceed(); 
     // do post work 
     return retVal; 
    } 
} 

Ancora, ogni parte ha i suoi pro/contro. Per esempio. gli interceptor sono più flessibili ma immagina di cambiare il nome del metodo, se usi un decoratore, probabilmente otterrai un errore del compilatore, con gli intercettori, semplicemente non corrisponderà e non eseguirà la tua logica 'intorno'.

+0

Un decoratore viene applicato automaticamente alle classi che implementano la stessa interfaccia (tranne l'utilizzo di un qualificatore personalizzato). Quindi più di una lezione decorata. – ammerzon

+0

D'accordo, è uno a uno o uno a più, ma ancora, hai l'interfaccia, quindi è fortemente orientata agli oggetti. Con AOP, è più flessibile perché puoi usare i filtri di tipo (ad es. Proxy tutti i metodi di alcune classi) così come i filtri di regola ex string (ad es. Proxy tutti i metodi che iniziano con select e fanno parte del pacchetto com.example.dao). – Bax

+0

Puoi aggiungere il tuo commento alla tua risposta con un esempio di filtri di regex matching – ammerzon

0

pittura molto simili a intercettori con due differenze interessanti:

  1. decoratore deve implementare l'interfaccia è decorando (ma può essere estratto, quindi non deve implementare i metodi)

  2. Un decoratore può avere un riferimento all'oggetto che decora. E 'fatto attraverso l'iniezione

Rif: https://blog.frankel.ch/cdi-an-overview-part-2

+0

Ma un intercettore può anche ottenere il riferimento con 'ic.getTarget()' – ammerzon

2

In generale, un decoratore viene utilizzato per aggiungere nuove funzionalità o modificare le funzionalità esistenti. Usa la composizione come alternativa all'eredità. I decoratori spesso forniscono API (metodi) aggiuntivi che non sono disponibili nelle classi decorate.

D'altra parte, AOP (ad esempio un intercettore) viene utilizzato per migliorare il comportamento esistente. Non aggiunge ulteriori API e generalmente non modifica le funzionalità esistenti. Viene attivato dall'invocazione di funzionalità esistenti e risponde intervenendo; ma la funzionalità esistente e l'API esistente rimangono invariate.

Non ho dimestichezza con le implementazioni JEE, quindi potrebbero aver offuscato le linee tra questi due modelli. Punti importanti da confrontare sarebbero,

  • È possibile che @Interceptor introduca nuovi metodi o esegua solo attorno ai metodi esistenti?
  • È possibile sostituire i metodi esistenti con @Interceptor o aggiungere solo comportamenti aggiuntivi?
  • È possibile applicare lo @Decorator ai pacchetti & gerarchie di classi oppure è vincolato da uno di questi?

In aggiunta alle differenze funzionali tra i due modelli, potrebbe anche essere interessante considerare le potenziali differenze di prestazioni. Mi aspetto che @Interceptor sia notevolmente più lento, dal momento che è necessario esaminare le chiamate dei metodi in fase di esecuzione, mentre le chiamate @Decorator possono essere risolte in fase di compilazione.