tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
12
ZUGRIFFE
931
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    ck2003 ck2003 ist offline Rookie
    Registriert seit
    Jun 2009
    Beiträge
    9
    Ich hab mich gestern mal bisschen mit AspectJ beschäftigt und irgendwie schein ich noch nicht so ganz dahinter zu kommen.

    Mal ein einfaches Beispiel. Nehmen wir an, ich hab folgenden Controller

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    @Controller
    public class TestControllerImpl {
     
        @RequestMapping(value="/test.do")
        @TestAnnotation
        public String test(TestForm form, HttpServletRequest request) {
            return "test";
        }
     
    }

    und den Abschnitt in meinem Aspect

    Code :
    1
    2
    3
    4
    5
    6
    7
    
        @Before(value = "testAnnotation() && args(form, request)")
        public void beforeValidation(Object form, HttpServletRequest request) {
            doSomething(form, request);
        }
     
            @Pointcut("@annotation(annotation.TestAnnotation)")
        public void testAnnotation() {}

    dann klappt das soweit.
    Jetzt implementier ich mal das Interface im TestControllerImpl

    Code :
    1
    2
    3
    4
    
    public interface TestController {
     
        public String test(TestForm form, HttpServletRequest request);
    }

    Bei der Einstellung Standard-Einstellung proxy-target-class="false" kommt
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    DEBUG - Creating shared instance of singleton bean 'testControllerImpl'
    DEBUG - Creating instance of bean 'testControllerImpl'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#0'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#1'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    DEBUG - Eagerly caching bean 'testControllerImpl' to allow for resolving potential circular references
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#0'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#1'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#0'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#1'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    DEBUG - Creating implicit proxy for bean 'testControllerImpl' with 0 common interceptors and 2 specific interceptors
    DEBUG - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [de.pixelcasino.frontend.controller.TestControllerImpl@1890909]
    DEBUG - Finished creating instance of bean 'testControllerImpl'
    und das mapping auf "test.do" klappt nichtmehr. Bei der proxy-target-class="true" ändert sich der output in
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    DEBUG - Creating shared instance of singleton bean 'testControllerImpl'
    DEBUG - Creating instance of bean 'testControllerImpl'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#0'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#1'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    DEBUG - Eagerly caching bean 'testControllerImpl' to allow for resolving potential circular references
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#0'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#1'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#0'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.flex.core.EndpointServiceMessagePointcutAdvisor#1'
    DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    DEBUG - Creating implicit proxy for bean 'testControllerImpl' with 0 common interceptors and 2 specific interceptors
    DEBUG - Creating CGLIB2 proxy: target source is SingletonTargetSource for target object [de.pixelcasino.frontend.controller.TestControllerImpl@1d1f4fe]
    DEBUG - Unable to apply any optimisations to advised method: public java.lang.String de.pixelcasino.frontend.controller.TestControllerImpl.test(javax.servlet.http.HttpSession,javax.servlet.http.HttpServletRequest)
    DEBUG - Found finalize() method - using NO_OVERRIDE
    DEBUG - Found 'hashCode' method: public native int java.lang.Object.hashCode()
    DEBUG - Unable to apply any optimisations to advised method: protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException
    DEBUG - Found 'equals' method: public boolean java.lang.Object.equals(java.lang.Object)
    DEBUG - Unable to apply any optimisations to advised method: public java.lang.String java.lang.Object.toString()
    DEBUG - Method is declared on Advised interface: public abstract int org.springframework.aop.framework.Advised.indexOf(org.aopalliance.aop.Advice)
    DEBUG - Method is declared on Advised interface: public abstract int org.springframework.aop.framework.Advised.indexOf(org.springframework.aop.Advisor)
    DEBUG - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isFrozen()
    DEBUG - Method is declared on Advised interface: public abstract org.springframework.aop.TargetSource org.springframework.aop.framework.Advised.getTargetSource()
    DEBUG - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvisor(org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException
    DEBUG - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvisor(int,org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException
    DEBUG - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setTargetSource(org.springframework.aop.TargetSource)
    DEBUG - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setPreFiltered(boolean)
    DEBUG - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isProxyTargetClass()
    DEBUG - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setExposeProxy(boolean)
    DEBUG - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isExposeProxy()
    DEBUG - Method is declared on Advised interface: public abstract org.springframework.aop.Advisor[] org.springframework.aop.framework.Advised.getAdvisors()
    DEBUG - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvice(int,org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException
    DEBUG - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvice(org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException
    DEBUG - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isPreFiltered()
    DEBUG - Method is declared on Advised interface: public abstract java.lang.Class[] org.springframework.aop.framework.Advised.getProxiedInterfaces()
    DEBUG - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isInterfaceProxied(java.lang.Class)
    DEBUG - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.removeAdvisor(org.springframework.aop.Advisor)
    DEBUG - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.removeAdvisor(int) throws org.springframework.aop.framework.AopConfigException
    DEBUG - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.replaceAdvisor(org.springframework.aop.Advisor,org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException
    DEBUG - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.removeAdvice(org.aopalliance.aop.Advice)
    DEBUG - Method is declared on Advised interface: public abstract java.lang.String org.springframework.aop.framework.Advised.toProxyConfigString()
    DEBUG - Method is declared on Advised interface: public abstract java.lang.Class org.springframework.aop.TargetClassAware.getTargetClass()
    DEBUG - Finished creating instance of bean 'testControllerImpl'
    und das ganze scheint zu klappen. Was mache ich falsch, dass das bei der Standardeinstellung nicht klappt.
    Geändert von ck2003 (07.06.09 um 16:52 Uhr)
     

  2. #2
    Avatar von Oliver Gierke
    Oliver Gierke Oliver Gierke ist offline Mitglied Rubin
    Registriert seit
    Dec 2003
    Ort
    Mannheim
    Beiträge
    1.457
    SpringAOP funktioniert im Defaultfall nur gegen Interfaces (Details in 6.1.3 hier. D.h. deine TestAnnotation müsste an das Interface um deinen Pointcut zu matchen. Durch proxy-target-class="true" kommt CGLib ins Spiel und es werden zur Laufzeit Subklassen deiner Beans erzeugt anstelle von wrappenden JDK Proxies. Dadurch gelangt die Annotation wieder in den Scope und der Pointcut matcht.

    Gruß
    Ollie
     
    In theory, there is no difference between theory and practice. In practice, there is!

    www.olivergierke.de

  3. #3
    ck2003 ck2003 ist offline Rookie
    Registriert seit
    Jun 2009
    Beiträge
    9
    Ok, dass die Annotation dann auch rüber muss war mir nicht klar, aber das wäre ja schnell gemacht.

    Davon abgesehen kommt er aber sowieso nie zu dem Punkt, weil das mapping auf "/test.do" gar nichtmehr erkannt wird.
    Code :
    1
    
        DEBUG - Rejected bean name 'testControllerImpl': no URL paths identified
     

  4. #4
    Avatar von Oliver Gierke
    Oliver Gierke Oliver Gierke ist offline Mitglied Rubin
    Registriert seit
    Dec 2003
    Ort
    Mannheim
    Beiträge
    1.457
    Was heißt "nicht mehr"? In welcher Konstellation denn?
     
    In theory, there is no difference between theory and practice. In practice, there is!

    www.olivergierke.de

  5. #5
    ck2003 ck2003 ist offline Rookie
    Registriert seit
    Jun 2009
    Beiträge
    9
    Erst hatte ich es so.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    @Controller
    public class TestControllerImpl implements TestController {
     
        @RequestMapping(value="/test.do")
        public String test(TestForm form, HttpServletRequest request) {
            return "test";
        }
     
    }
     
    public interface TestController {
     
        @TestAnnotation
        public String test(TestForm form, HttpServletRequest request);
    }

    Dann findet er im DefaultAnnotationHandlerMapping aber das @Controller nichtmehr als Annotation, weswegen er gar nicht erst versucht die URLs zu extrahieren. Wenn ich mal testweise das @Controller zusätzlich ans Interface setze, was wohl nicht im Sinne Erfinders ist, findet er das zwar dann, aber spätestens beim Extrahieren von @RequestMapping gibt er auf.
     

  6. #6
    Avatar von Oliver Gierke
    Oliver Gierke Oliver Gierke ist offline Mitglied Rubin
    Registriert seit
    Dec 2003
    Ort
    Mannheim
    Beiträge
    1.457
    Sicher? Hast du die Logausgaben für die Konfiguration mal da? Hab grad mal im Code geschaut und seh keinen Grund warum das nicht tun sollte...
     
    In theory, there is no difference between theory and practice. In practice, there is!

    www.olivergierke.de

  7. #7
    ck2003 ck2003 ist offline Rookie
    Registriert seit
    Jun 2009
    Beiträge
    9
    Was sollte gehen? Wenn @Controller und @RequestMapping in TestControllerImpl liegen? Hab ich da was falsch konfiguriert? An den Annotation in TestControllerImpl selbst kommt er bei mir nie vorbei.

    Außer
    Code :
    1
    
    DEBUG - Rejected bean name 'testControllerImpl': no URL paths identified
    loggt der bei mir in dem Bereich zu dem Fall nix oder könnte davor oder dahinter noch was spannendes für dich auftauchen.
     

  8. #8
    Avatar von Oliver Gierke
    Oliver Gierke Oliver Gierke ist offline Mitglied Rubin
    Registriert seit
    Dec 2003
    Ort
    Mannheim
    Beiträge
    1.457
    Ich meine, dass es so funktionieren sollte, wie du es da hast... Die kritische Methode ist wohl DefaultAnnotationHandlerMapping.determineUrlsForHandler(String beanName). Da wirft er deine Bean weg, obwohl er das nicht sollte. Da solltest du mal den Debugger drauf ansetzen und schauen, was da drin genau passiert.
     
    In theory, there is no difference between theory and practice. In practice, there is!

    www.olivergierke.de

  9. #9
    ck2003 ck2003 ist offline Rookie
    Registriert seit
    Jun 2009
    Beiträge
    9
    Mal am Beispiel von
    Code :
    1
    
    AnnotationUtils.findAnnotation(handlerType, Controller.class)
    was im unteren Bereich der angesprochenen Methode zu finden ist.

    Zuerst schaut er im Proxy selbst: der hat die Annotation nicht.

    Dann geht er die Interfaces durch.:
    TestController
    org.springframework.aop.SpringProxy
    org.springframework.aop.framework.Advised

    als nächstes geht er auf die Superklasse
    java.lang.reflect.Proxy

    die hat nur
    Serializable

    und dann kommt noch java.lang.Object dran

    wer von denen sollte denn nun die Annotationen von TestControllerImpl vorhalten?
     

  10. #10
    Avatar von Oliver Gierke
    Oliver Gierke Oliver Gierke ist offline Mitglied Rubin
    Registriert seit
    Dec 2003
    Ort
    Mannheim
    Beiträge
    1.457
    Args, daran hab ich nicht gedacht... wenn die Klasse geproxied wird, dann hat sie natürlich nicht mehr den Typ der Implemenierung. Damit sind auch die Annotationen nicht mehr sichtbar. Hast du mal geschaut, ob es a) nen Bug dazu im JIRA gibt? und/oder b) es im 3.0 Milestone evtl. schon gefixt ist?

    EDIT: Hab grad kurz mit Eberhard Wolff gesprochen. Scheint tatsächlich ein Bug zu sein. Ich konnte auf die Schnelle im JIRA nix finden. Ich file da morgen früh mal was...
     
    In theory, there is no difference between theory and practice. In practice, there is!

    www.olivergierke.de

  11. #11
    ck2003 ck2003 ist offline Rookie
    Registriert seit
    Jun 2009
    Beiträge
    9
    Danke erstmal; dann weiß ich ja schonmal wo ich dran bin.

    edit: Ich würd sagen der triffts ganz gut.
    http://jira.springframework.org/browse/SPR-5084
     

  12. #12
    Avatar von Oliver Gierke
    Oliver Gierke Oliver Gierke ist offline Mitglied Rubin
    Registriert seit
    Dec 2003
    Ort
    Mannheim
    Beiträge
    1.457
    Du kannst in der Zwischenzeit ja einfach die Annotationen an das Interface nageln. Das hast du vermutlich ja eh nur eingeführt um AOP ohne CGLib nutzen zu können.

    Gruß
    Ollie
     
    In theory, there is no difference between theory and practice. In practice, there is!

    www.olivergierke.de

  13. #13
    ck2003 ck2003 ist offline Rookie
    Registriert seit
    Jun 2009
    Beiträge
    9
    Genau aus dem Grund; darum ist es auch nicht lebensnotwendig.
    Aber die ans Interface zu setzen klappt leider nicht, weil @RequestMapping auf Methoden-Ebene nur bei Superklassen, nicht bei Interfaces überprüft wird. Darum lass ichs erstmal so und behalte das Ganze im Auge.
     

Ähnliche Themen

  1. [Spring] ResourceMessages in Controller oder Beans?
    Von Hardi82 im Forum Enterprise Java (JEE, J2EE, Spring & Co.)
    Antworten: 4
    Letzter Beitrag: 27.10.08, 08:49
  2. Spring: Bean-Initialisierung in einem Webprojekt -> NullPointerException
    Von Wilde im Forum Enterprise Java (JEE, J2EE, Spring & Co.)
    Antworten: 1
    Letzter Beitrag: 01.10.08, 08:30
  3. Komisches Verhalten von einem.net Programm
    Von Bellm im Forum .NET Café
    Antworten: 9
    Letzter Beitrag: 18.09.08, 16:09
  4. Spring / DispatcherServlet: MVC - Controller
    Von gtm im Forum Enterprise Java (JEE, J2EE, Spring & Co.)
    Antworten: 0
    Letzter Beitrag: 18.08.08, 18:05
  5. Antworten: 0
    Letzter Beitrag: 28.04.08, 11:29