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;
}
Sie haben Recht. Ich habe auch
@EnableTransactionManagement
konfiguriert auf einer zweiten Konfigurationsklasse, aber ohneproxyTargetClass = 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@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. –
@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. –