Quando la gerarchia di classi non è lineare, l'aspetto non viene attivato quando definito sull'interfaccia di base.Spring (Java): l'aspetto non viene attivato nella gerarchia di classi non lineari
Il più interessante: quando si aggiunge l'implementazione delegante (vedere l'ultimo blocco di codice) alla classe padre dell'implementazione, il test diventa Verde (l'Aspetto viene attivato come previsto).
Domanda: Perché non funziona come descritto nell'esempio e perché funziona con la delega dell'implementazione?
Esempio (mi dispiace, ad esempio non inferiore trovato):
prova:
@Autowired
private TheInterface underTest;
private static boolean aspectCalled;
private static boolean implementationCalled;
@Test
public void aspectTest() throws Exception {
aspectCalled = false;
implementationCalled = false;
underTest.doSomething();
assertTrue("Implementation not called!", implementationCalled);
assertTrue("Aspect not called!", aspectCalled);
}
Aspetto:
@Aspect
@Component
public static class MyAspect {
@Before("execution(* *..SpecializedInterface+.doSomething())")
public void applyAspect() {
aspectCalled = true;
}
}
Interfacce:
Abstract I mplementations (modello Template):
public static abstract class BaseTemplate implements TheInterface {
abstract void doOneStep();
@Override
public void doSomething() {
// do some stuff and
doOneStep();
}
}
public static abstract class SpecializedTemplate extends BaseTemplate implements SpecializedInterface {
// some other methods
}
fagioli Implementazione:
@Component
public static class TemplateImplementation extends SpecializedTemplate {
@Override
void doOneStep() {
implementationCalled = true;
}
}
(Se siete interessati: configurazione di prova :)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyConfig.class)
public class AopTest {
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackageClasses = AopTest.class)
public static class MyConfig {
}
...
soluzione Ugly: Aggiungi questo frammento di SpecializedTemplate
@Override
public void doSomething() {
super.doSomething();
}
Quindi, perché questa soluzione alternativa è necessaria?
Non sono troppo preciso nei dettagli, ma questa è la mia ipotesi: @Before ("esecuzione (* * .. SpecializedInterface + .doSomething())") dice di applicare l'aspetto a doQualcosa() in qualsiasi classe implementazione di SpecializedInterface. SpecializedTemplate non contiene doSomething() (bytecode-saggio), quindi l'aspetto non viene applicato. Una volta aggiunta la soluzione, la classe contiene il metodo e l'aspetto può essere applicato. –
Ma cos'è la TemplateImplementation (implementazione bean)? Contiene il metodo doSomething() - in bytecode? Il compilatore java copia tutte le implementazioni in classi astratte nelle classi concrete, quindi ha il metodo anche a livello di byte di codice? –
No, TemplateImplementation non ha il bytecode per i metodi ereditati. Se si chiama doSomething() su TemplateImplementation, la Java VM durante il runtime passa all'indietro attraverso la gerarchia delle classi finché non trova un'implementazione. Se si utilizza la soluzione alternativa, troverà l'implementazione in SpecializedTemplate, in cui è stato applicato l'aspetto (dal momento che il collegamento di punti corrisponde). Senza soluzione di continuità deve tornare a BaseTemplet, dove l'aspetto non è stato applicato (dal momento che non corrispondeva al punto) –