Skip to content

Bean's type is changed unexpectedly when Spring AOP is used [SPR-12190] #16804

Closed
@spring-projects-issues

Description

@spring-projects-issues

Jeff Fang opened SPR-12190 and commented

When a bean whose class type implements an interface is intercepted by a Spring AOP, the bean is not the original bean class type, but is the JDK proxy class which implements the bean's interface.

For example, we define an ICalculatorService interface, and an IntensiveCalculatorService class implementing the ICalculatorService interface. And we define an intensiveCalculatorService bean with the IntensiveCalculatorService class in the spring configuraiton file, and intercept the IntensiveCalculatorService.calculator method with spring AOP.

The unexpected thing occurs. We cannot cast the "intensiveCalculatorService" bean to an IntensiveCalculatorService class object, though the bean defined as IntensiveCalculatorService class, because it actually is not an object of IntensiveCalculatorService class, but is JDK proxy object which implements ICalculatorService interface.

Let's imagine the scenario, a developer A only defined the intensiveCalculatorService bean, and cast the bean to a IntensiveCalculatorService type . It's definitely correct because there is no AOP defined. But the developer A's coworker B want to intercept the IntensiveCalculatorService.calcualtor to do something before the caculator. He defined the AOP aspect in the spring configuration file. The original code of using IntensiveCalculatorService type bean throwed ClassCastException.

The severity thing is that developer A and B have no sense of the exception happening.

Though we could use proxy-target-class="true" to force the use of CGLib proxy to solve the problem, I think it needs improvement in spring AOP. Bean's type is changed unexpectedly when Spring AOP is used without proxy-target-class property set. Maybe there are some conerns to try the JDK original proxy mechanism first, and avoid depending the thirdparty lib. At least I think the issue needs enhancement to warn users the unexpected behavior of bean's type being changed.

The code is below:

package com.performance.service;
public interface ICalculatorService {
   public void calculator(int count);
}

package com.performance.service;
public class IntensiveCalculatorService implements ICalculatorService
{
   public String type = "intensive";
  
   public void testObjectSelfMethod(){
        System. out.println("This is IntensiveCalculatorService Self Method");
   }

   public void calculator(int count){
        System. out.println("intensive calculator");
    }
}

The Spring configuration file is below:

<aop:config >  
   <aop:aspect id= "TestAspect" ref ="aspectBean">   
        <aop:pointcut id= "ics" 
            expression="execution(* com.performance.service.IntensiveCalculatorService.calculator(..))" />   
        <aop:around pointcut-ref="ics" method="aroundMethod"/>    
    </aop:aspect>   
</aop:config >  

<bean id="aspectBean" class="com.performance.aspect.TestAspect" />

<bean id= "intensiveCalculatorService" class="com.performance.service.IntensiveCalculatorService" />

The following code will throw ClassCastException in the runtime.

IntensiveCalculatorService intensiveCalculatorService = (IntensiveCalculatorService)context.getBean("intensiveCalculatorService" );

Exception in thread "main" java.lang.ClassCastException: $Proxy0 cannot be cast to com.performance.service.IntensiveCalculatorService
at com.performance.main.ApplicationMain.main(ApplicationMain.java:20)


Issue Links:

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)status: bulk-closedAn outdated, unresolved issue that's closed in bulk as part of a cleaning process

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions