2015-03-16 3 views
5

Eigentlich bin ich verwirrt über das Verhalten von Federproxys. Ich denke, ich kenne den Hauptunterschied zwischen den Proxy-Mechanismen von j2ee, cglib und aspectj. Ich habe den aspectj automatischen Proxy in meiner Konfigurationsklasse aktiviert und aspectj ist im Klassenpfad enthalten.Spring AOP Proxy funktioniert nicht wie erwartet

Meine Konfiguration

@Configuration 
@EnableAspectJAutoProxy(proxyTargetClass = true) 
public class ApplicationConfiguration { 
    ... 
} 

AspectJ Abhängigkeit

<dependency> 
    <groupId>org.aspectj</groupId> 
    <artifactId>aspectjrt</artifactId> 
    <version>1.8.5</version> 
</dependency> 

Durch diese einfache Setup mit mir, dass die Bohne Injektionsarbeiten wie vorgesehen angenommen habe. Aber stattdessen führt meine Anwendung in IllegalArgumentException s mit Nachrichten wie "Kann Feld [...] zu com.sun.proxy nicht einstellen. $ Proxy30". Das bedeutet, dass Spring den j2ee-Proxy für meinen Dienst verwendet, auch wenn aspectj proxy aktiviert ist.

Endlich habe ich herausgefunden, dass die Schnittstellen auf meinem Dienst dieses Verhalten verursacht. Es scheint, dass der Frühling beschließt, den j2ee-Proxy zu verwenden, wenn mein Dienst irgendeine Schnittstelle implementiert. Wenn ich sie entferne, funktioniert es.

Fehler:

@Service 
@Validated 
public class MyService implements Interface1, Interface2 { 

    @override 
    public void methodFromInterface1() { 
    } 

    @override 
    public void methodFromInterface2() { 
    } 

    public void serviceMethod() { 
    } 
} 

OK:

@Service 
@Validated 
public class MyService { 

    public void methodFromInterface1() { 
    } 

    public void methodFromInterface2() { 
    } 

    public void serviceMethod() { 
    } 
} 

Bis jetzt habe ich verstehen, dass Schnittstellen für die J2EE-Proxy erforderlich sind. Aber es ist neu für mich, dass ein cglib/aspectj-Proxy nicht mit Beans funktioniert, die Schnittstellen implementieren.

Gibt es eine Möglichkeit zu ...

... Kraftfeder nicht j2ee Proxies zu verwenden?

... force spring um cglib/aspectj proxies zu verwenden (auch für Klassen mit Schnittstellen)?

Ist das ein Fehler oder ein gewünschtes Verhalten des Frühlings?

bearbeiten: Beispiel aktualisiert, @Transational durch @Validated ersetzt

Edit2: Lösung:@Validated wird durch die MethodValidationPostProcessor betroffen. Daher muss die Eigenschaft proxyTargetClass für diese Bean auf true gesetzt werden.

@Bean 
public MethodValidationPostProcessor methodValidationPostProcessor() { 
    final MethodValidationPostProcessor methodValidationPostProcessor; 
    methodValidationPostProcessor = new MethodValidationPostProcessor(); 
    methodValidationPostProcessor.setProxyTargetClass(true); 
    return methodValidationPostProcessor; 
} 

Antwort

2

@EnableAspectJAutoProxy Anmerkung gilt für @Aspect Anmerkungen, nicht auf @Transactional Anmerkungen. Dafür müssen Sie @EnableTransactionManagement Annotation auf @Configuration Klasse mit proxyTargetClass = true Attributwert haben.

@Configuration 
@EnableAspectJAutoProxy(proxyTargetClass = true) 
@EnableTransactionManagement(proxyTargetClass = true) 
public class ApplicationConfiguration { 
    ... 
} 
+0

Sie haben Recht. Ich habe auch @EnableTransactionManagement konfiguriert auf einer zweiten Konfigurationsklasse, aber ohne proxyTargetClass = true, und aus irgendeinem Grund funktioniert es. Bitte beachten Sie, dies ist nur ein Beispiel und das Problem ist reproduzierbar mit @Validated auf der Serviceklasse. – baymon

+0

@baymon Genau. Sie müssen also "proxyTargetClass = true" auf diese Annotation setzen, um den CGLib-Proxy für mit Annotationen versehene '@ Transactional'-Klassen verwenden zu können. –

+1

@baymon Wenn Sie Spring AOP nicht verwenden, brauchen Sie nicht einmal die Annotation @ @ EnableAspectJAutoProxy. Um den aspect_proxy bei der Transaktion zu aktivieren, können Sie das 'mode' Attribut der' @ EnableTransactionManagement' Annotation verwenden. –

Verwandte Themen