0

I'm trying AOP for the first time and for that I've developed a small and easy example for that but I'm finding some problems. Firstly, Spring asks me for adding a dependency to cglib library by printing the following error:

cannot proxy target class because cglib2 is not available

After solving that and adding the dependency to my pom.xml file:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2</version>
</dependency>

I found cglib creates a proxy of every bean of mine and the methods don't get executed. Here you can see:

Class A: package com.test.test.classes;

public abstract class A {
    public abstract void doMoreStuff();

    public void doStuff(){
        System.err.println("Inside A.doStuff()");
    }
}

Class B package com.test.test.classes;

public class B extends A{
    @Override
    public void doMoreStuff() {
        System.err.println("Inside B.doMoreStuff()");
   }
}

Class C package com.test.test.classes;

public class C extends A{
    @Override
    public void doMoreStuff() {
        System.err.println("Inside C.doMoreStuff()");
   }
}

Aspect package com.test.test.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectAttempt {
    @Around("execution(* com.test.test.classes.*.*(..))")
    public void miAspecto(ProceedingJoinPoint joinPoint) throws Throwable{
        System.err.println("Inside the Aspect");
        System.err.println("Invoking " + joinPoint.getSignature());
    }   
}

Spring Context

<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"
    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 "
    default-autowire="byName">

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

    <bean id="a1" class="com.test.test.classes.B" />
    <bean id="a2" class="com.test.test.classes.C" />
    <bean id="b" class="com.test.test.classes.B" />
    <bean id="c" class="com.test.test.classes.C" />

    <!-- Aspect -->
    <bean id="logAspect" class="com.test.test.aspect.AspectAttempt" />

</beans>

Test package com.test.test.testingAspects;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.test.test.classes.A;
import com.test.test.classes.B;
import com.test.test.classes.C;

/**
 * Unit test for simple App.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { 
        "classpath:/context.xml" })
public class AppTest  {

    @Autowired
    @Qualifier("a1")
    private  A a1;
    @Autowired
    @Qualifier("a2")
    private  A a2;
    @Autowired
    @Qualifier("b")
    private  B b;
    @Autowired
    @Qualifier("c")
    private  C c;

    @Test
    public void test() {

        a1.doStuff();
        a2.doStuff();
        a1.doMoreStuff();
        a2.doMoreStuff();
        b.doStuff();
        b.doMoreStuff();
        c.doStuff();
        c.doMoreStuff();    
    }
}

Console log

29-oct-2015 10:47:33 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
INFO: @TestExecutionListeners is not present for class [class com.test.test.testingAspects.AppTest]: using defaults.
29-oct-2015 10:47:33 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [context.xml]
29-oct-2015 10:47:33 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@149eb9f: startup date [Thu Oct 29 10:47:33 CET 2015]; root of context hierarchy
29-oct-2015 10:47:33 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@40afb9: defining beans [org.springframework.aop.config.internalAutoProxyCreator,a1,a2,b,c,logAspect,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy
Inside the Aspect
Invoking void com.test.test.classes.A.doStuff()
Inside the Aspect
Invoking void com.test.test.classes.A.doStuff()
Inside the Aspect
Invoking void com.test.test.classes.B.doMoreStuff()
Inside the Aspect
Invoking void com.test.test.classes.C.doMoreStuff()
Inside the Aspect
Invoking void com.test.test.classes.A.doStuff()
Inside the Aspect
Invoking void com.test.test.classes.B.doMoreStuff()
Inside the Aspect
Invoking void com.test.test.classes.A.doStuff()
Inside the Aspect
Invoking void com.test.test.classes.C.doMoreStuff()
29-oct-2015 10:47:36 org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@149eb9f: startup date [Thu Oct 29 10:47:33 CET 2015]; root of context hierarchy
29-oct-2015 10:47:36 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@40afb9: defining beans [org.springframework.aop.config.internalAutoProxyCreator,a1,a2,b,c,logAspect,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy

Any idea what the problem might be?

Thanks in advance

Fernando
  • 751
  • 2
  • 13
  • 27

2 Answers2

1

As far I can see the final method is not invoked because all the methods are being captured by your AspectAttempt Aspect but the execution does not continue.

So if you want to proceed with the real call you will need to edit in your AspectAttempt.miAspecto like this:

@Aspect
public class AspectAttempt {
    @Around("execution(* com.test.test.classes.*.*(..))")
    public void miAspecto(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Inside the Aspect");
        System.out.println("Invoking " + joinPoint.getSignature());
        joinPoint.proceed();
    }
}

See that the only new is jointPoint.proceed() call.

Hope it helps.

Gerard Ribas
  • 717
  • 1
  • 9
  • 17
  • There's so much to have in mind I completely forgot, thank you so much! I even forgot to return the result type joinPoint.proceed() returns. – Fernando Oct 29 '15 at 12:23
0

spring reference:

Around advice is declared using the @Around annotation. The first
parameter of the advice method must be of type ProceedingJoinPoint. 
Within the body of the advice, calling proceed() on the 
ProceedingJoinPoint causes the underlying method to execute
denis.zhdanov
  • 3,734
  • 20
  • 25