1
votes

I struggle to use aspect in Spring MVC project.

Method that is a pointcut is running fine, but without advise.

Here is class, that starts whole spring boot and that is root of spring context:

@Lazy
@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass=true)
@Configuration
public class MainSpringBootClass{
    public static void main(String[] args)
    {
        SpringApplication.run(MainSpringBootClass.class, args);
    }
}

Here is class with method, that is pointcut.

@Component
@Log
@Aspect
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class MyExampleClass
{
    public void example()
    {
        System.out.println("example");
    }
}

And here is my aspect:

@Aspect
@Component
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class MyAspect implements MethodBeforeAdvice
{
    @Pointcut("execution(* com.example.MyExampleClass.example())")
    public void asd()
    {
        // pointcut
    }

    @Before("asd()")
    public void login()
    {
        System.out.println("im am logging in");
    }

    @Before("execution(* com.example.MyExampleClass.example())")
    public void login2()
    {
        System.out.println("im am logging in2");
    }

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable
    {
        System.out.println("aop before");
    }
}

And here is my controller:

@RestController
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class MyExampleController
{
    private final MyExampleClass myExampleClass;

    @Inject
    public AdController(MyExampleClass myExampleClass)
    {
        this.myExampleClass = myExampleClass;
    }

    @RequestMapping("/")
    public String index()
    {
        myExampleClass.example();

        return "x";
    }
}

As You can see, I have been trying to bruteforce correct result with annotations. I have also seen on some website, that I need specific dependencies, so here are mine (pasting only those, related to aspects):

compile 'org.springframework:spring-aop:+'
compile 'org.aspectj:aspectjrt:+'
compile 'org.aspectj:aspectjweaver:+'
compile 'cglib:cglib:+'
compile 'cglib:cglib-nodep:+'

All dependencies have been successfully downloaded, project compiles and runs fine. When I hit localhost:8080 then I see returned value "x", and inside logs I see "example". However, I do not see any advices from spring aop nor aspectj - what am I doing wrong?

I am just using this project as sandbox to learn aspects, so I would be eager to learn, how to do it with each of Spring AOP and AspectJ. The most important thing for me is to do it all without XML.

EDIT: I have added simple constructor to MyAspect with println to check, if it is created (as it is normal spring bean with @Component after all) and it does - it is correctly created by spring.

EDIT 2: IntelliJ IDEA tells me about methods login and login2: "This advice advices no method", but at the same time, I am able to jump (with control-click) from string, that is value in annotations to correct implementations.

1
Something to try would be to make sure your pointcut syntax isn't missing something. e.g. what if you try to broaden it like this: @Before("execution(* com.example.MyExampleClass.*(..))")pastafarian
it is correct - IntelliJ IDEA let's me jump to correct method, when I control-click it. I have also tried adding two dots and boarding range with * - still no expected output (but everything runs).xinus01
could be a dependency issue? you could try using mvnrepository.com/artifact/org.springframework.boot/… instead of mvnrepository.com/artifact/org.springframework/spring-aop (initially you can try to simplify by taking out the aspectj references just to see if it works)pastafarian
I have replaced dependency of AOP as You suggested - nothing changes. Removing AspectJ dependency along @Aspect annotations also doesn't do anything.xinus01
You need @EnableAspectJAutoProxy only one time on the @Configuration class, not on every class...Evgeni Dimitrov

1 Answers

0
votes

All you should need is something like this:

@Aspect
@Component
public class MyAspect {

    @Before("execution(* com.example.MyExampleClass.example(..))")
    public void logBefore(JoinPoint pjp) throws Throwable {
        System.out.println("before...");
    }
}

You might have to replace all of the aspectJ dependencies with spring-boot-starter-aop .

Here's an example project that works (see RestControllerAspect.java):

https://github.com/khoubyari/spring-boot-rest-example