linux developer
linux developer

Reputation: 831

Seeing odd behavior when learning SpringAOP using @AspectJ style

Iam a new bee to Spring Framework and i am referring to documentation available with spring projects.

In the process i am also learning a new concept AOP. I am following the spring documentation to try out some samples http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

I tried to use "@AspectJ" style for my first Aspect Helloworld using Spring AOP.

This is my context config file

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context" 
    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.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd">

     <aop:aspectj-autoproxy expose-proxy="false" />

    <context:annotation-config></context:annotation-config>

    <bean id="aoProgrammingAspectJ" class = "com.AOProgramming.AOProgrammingAspectJ">
    </bean>


    <bean id="aoProgrammingImpl" class = "com.AOProgramming.AOProgrammingImpl">
    </bean>

</beans>

This is a simple interface

package com.AOProgramming;

public interface AOProgrammingInterface {

    public void startAspecting();

}

I implement this interface

package com.AOProgramming;

public class AOProgrammingImpl implements AOProgrammingInterface {


    @Override
    public void startAspecting() {

        System.out.println("THe Aspecting has just begun for :");

    }
}

This is where i am defining the aspect definition for pointcut and advice

package com.AOProgramming;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;


@Aspect
public class AOProgrammingAspectJ {

    @Pointcut("execution( * com.AOProgramming.*.*(..))")
    public void cuttingOne() {}

    @Before("cuttingOne()")
    public void adviceCuttingOne1(){

        System.out.println("This is the at the beginning");

    }



}

This is my actual INVOKER class

package com.AOProgramming;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AOProgrammingInvokerApp {

    public static void main(String[] args){

        ApplicationContext context = new ClassPathXmlApplicationContext("AOProgramming-servlet.xml");

        AOProgrammingImpl obj = (AOProgrammingImpl) context.getBean("aoProgrammingImpl");

        obj.startAspecting();

    }

}

When i tried to execute the sample i am getting the following Error

Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy6 cannot be cast to com.AOProgramming.AOProgrammingImpl
    at com.AOProgramming.AOProgrammingInvokerApp.main(AOProgrammingInvokerApp.java:12)

I am trying to re-read the complete page still i have the same issue also not getting enough material dealing with latest Spring AOP samples. All pre-dates to 2002 or 2008 which has different way of explaining SpringAOP.

Can someone help me to understand what i missed here

Appreciate your help

Upvotes: 0

Views: 143

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280132

To understand this you need to understand how JDK proxies work and what their limitations are (and the alternative, CGLIB proxies). In short, JDK proxies only keep the type of your target bean's interfaces. So the proxy generated for AOProgrammingImpl will be of type AOProgrammingInterface but not AOProgrammingImpl even though the target is of type AOProgrammingImpl.

You can change this

AOProgrammingImpl obj = (AOProgrammingImpl) context.getBean("aoProgrammingImpl");

to this

AOProgrammingInterface obj = (AOProgrammingInterface) context.getBean("aoProgrammingImpl");

Or you can add CGLIB to your classpath and change your config to

<aop:aspectj-autoproxy expose-proxy="false" proxy-target-class="true" />

so that Spring uses CGLIB proxies which work with class type.

Upvotes: 2

Related Questions