Results 1 to 3 of 3

Thread: "overriding" final method with @DeclareParents?

  1. #1
    Join Date
    Sep 2007
    Location
    Bratislava, Slovakia
    Posts
    4

    Default "overriding" final method with @DeclareParents?

    Hi,

    I was playing little bit with @DeclareParents annotation and I found some strange thing, which I don't understand: by using @DeclareParents I was able to call different implementation instead of final method. I don't know whether this is feature or bug... Can anybody explain this to me?

    This is what I did:

    I've created FooBar interface and one implementation with final method.

    FooBar interface
    Code:
    package spring.example.aop.introduction;
    
    public interface FooBar {
    	public int foo(int bar);
    }
    FooBarImpl class
    Code:
    package spring.example.aop.introduction;
    
    public class FooBarFinalImpl implements FooBar {
    	public final int foo(int bar) {
    		return bar+3;
    	}	
    }
    Main class
    Code:
    package spring.example.aop.introduction;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class ApplicationRunner {
    
    	public static void main(String[] args) {
    		ApplicationContext context = new ClassPathXmlApplicationContext("app-context.xml");
    
    		FooBar fooBar = (FooBar)context.getBean("foobar");
    		System.out.println(fooBar.foo(5));	
    	}
    }
    app-context.xml
    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    						http://www.springframework.org/schema/aop
    						http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
    
    	<bean name="foobar" class="spring.example.aop.introduction.FooBarFinalImpl"/>
    	
    	<aop:aspectj-autoproxy/>
    
    </beans>
    When I ran the application, I got output: 8
    which is 5 + 3... that's ok

    Then I created another implementation of the FooBar interface
    Code:
    package spring.example.aop.introduction;
    
    public class FooBarAnotherImpl implements FooBar {
    	public int foo(int bar) {
    		return 0;
    	}
    }
    Also I created another interface called ZigZag with only one method foo(int) with same signature as in FooBar interface
    Code:
    package spring.example.aop.introduction;
    
    public interface ZigZag {
    	public int foo(int bar);
    }
    Finally, I created FooBar introduction and annotated it with @DeclareParents:
    Code:
    package spring.example.aop.introduction;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    
    @Aspect
    public class FooBarIntroduction {
    	
    	@DeclareParents(
    			value="spring.example.aop.introduction.FooBarFinalImpl",
    			defaultImpl = FooBarAnotherImpl.class
    	)
    	public ZigZag zigZag; //this is by purpose
    
    }
    And also I updated config file and main class:
    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    						http://www.springframework.org/schema/aop
    						http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
    
    	<bean name="foobar" class="spring.example.aop.introduction.FooBarFinalImpl"/>
    	<bean class="spring.example.aop.introduction.FooBarIntroduction"/>
    	
    	<aop:aspectj-autoproxy/>
    
    </beans>
    Code:
    package spring.example.aop.introduction;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class ApplicationRunner {
    
    	public static void main(String[] args) {
    		ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/aop-int-context.xml");
    
    		FooBar fooBar = (FooBar)context.getBean("foobar");
    		System.out.println(fooBar.foo(5));	
    		ZigZag zigZag = (ZigZag)fooBar;
    		System.out.println(zigZag.foo(99));
    	}
    }
    Now when I run the application, I will get following output:
    0
    0

    So this means that it was executed foo() method implemented in FooBarAnotherImpl even the foo() method in FooBarFinalImpl is final.

    If I replace ZigZag in FooBarIntroduction class with FooBar, it works differently... I will get output 8... final method is executed by proxy.

    Is this feature? Why it works like this?

    Thanks
    Peter
    Last edited by peter.zozom; Feb 4th, 2011 at 08:48 AM.

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    As you already state it is a proxy which is basically a wrapper around your actual class it isn't an extension. If you try using classproxies you will see different behavior (you will not be able to do the same as well the method is final). But with interface proxies it works just fine...
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Sep 2007
    Location
    Bratislava, Slovakia
    Posts
    4

    Default

    Quote Originally Posted by Marten Deinum View Post
    As you already state it is a proxy which is basically a wrapper around your actual class it isn't an extension. If you try using classproxies you will see different behavior (you will not be able to do the same as well the method is final). But with interface proxies it works just fine...
    But my point is that if I declare FooBarAnotherImpl as parent to FooBarFinalImpl (both implementing the same interface - FooBar) and FooBarIntroduction looks like this:
    Code:
    package spring.example.aop.introduction;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    
    @Aspect
    public class FooBarIntroduction {
    	
    	@DeclareParents(
    			value="spring.example.aop.introduction.FooBarFinalImpl",
    			defaultImpl = FooBarAnotherImpl.class
    	)
    	public FooBar fooBar;
    
    }
    ...in that case it will execute FooBarFinalImpl.foo()... so final method is executed.

    Instead, if I change FooBarIntroduction to use ZigZag interface like this:
    Code:
    package spring.example.aop.introduction;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    
    @Aspect
    public class FooBarIntroduction {
    	
    	@DeclareParents(
    			value="spring.example.aop.introduction.FooBarFinalImpl",
    			defaultImpl = FooBarAnotherImpl.class
    	)
    	public ZigZag zigZag; //this is only change
    
    }
    ... but leaving both implementations unchanged, it will execute FooBarAnotherImpl.foo() so final method is not executed.

    In both cases FooBarFinalImpl and FooBarAnotherImpl are implementing FooBar interface and no class is implementing ZigZag iterface (only the dynamically created proxy).

    So my question is:
    Why is proxy behaving like that when adding new interface (ZigZag) to FooBarIntroduction class which has nothing to do with FooBarFinalImpl and FooBarAnotherImpl?
    Last edited by peter.zozom; Feb 7th, 2011 at 02:19 AM. Reason: typo

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •