I'm trying to capture the execution of an advice using annotation in Maven, but it says that advice has not been applied. Here is the code:
package testMaven8;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
#Aspect
public class aspecter {
public static int a;
public void setA(int a) {
this.a = a;
}
public int getA() {
return a;
}
#Before("execution(* testMaven8.das.qwe(..))")
public void testBefore2(){
System.out.println("yoo2");
setA(102);
System.out.println(a);
}
#Before("execution (* testMaven8.aspecter.testBefore2(..))")
public void advice1(){
System.out.println("advicing advice testBefore2");
}
}
Is there something wrong with the code? I'm trying to avoid the usage of Aspect class if it's possible. Any help is appreciated.
Thanks
Advice execution is something special in AspectJ, not a normal method execution. Thus, if you want to capture advice execution you also need a special pointcut with the surprising name - adviceexecution() ;-)
Here is some sample code:
Driver application:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new Application().doSomething();
}
public void doSomething() {
System.out.println("Doing something");
}
}
Aspect capturing method executions:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class MethodInterceptor {
#Before("execution(!static * *(..))")
public void interceptMethod(JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint);
}
}
Aspect capturing advice executions:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class AdviceInterceptor {
#Before("!within(AdviceInterceptor) && adviceexecution()")
public void interceptAdvice(JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint);
}
}
Please do not try to pack the advice execution interceptor into the same aspect as another advice because you can easily end up in an endless recursion if you cannot exclude the adviceexecution() pointcut from capturing itself via !within(AdviceInterceptor).
Console log:
adviceexecution(void de.scrum_master.aspect.MethodInterceptor.interceptMethod(JoinPoint))
execution(void de.scrum_master.app.Application.doSomething())
Doing something
Related
If i keep #Pointcut("within(org.example.ShoppingCart.*)") in AuthenticationAspect.java then the authenticate method is NOT getting invoked BUT when i change to #Pointcut("within(org.example..*)") then it does get invoked.
Doesn't the 2nd PointCut below automatically include the first one?
#Pointcut("within(org.example.ShoppingCart.*)")
#Pointcut("within(org.example..*)")
i believe both of these should work.
Following is the code :
ShoppingCart.java
package org.example;
import org.springframework.stereotype.Component;
#Component
public class ShoppingCart {
public void checkout(String status)
{
System.out.println("Checkout method called");
}
}
AuthenticationAspect.java
package org.example;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class AuthenticationAspect {
#Pointcut("within(org.example.ShoppingCart.*)")
public void authenticationPointCut()
{
}
#Before("authenticationPointCut()")
public void authenticate()
{
System.out.println("Authentication is being performed");
}
}
Main.java
package org.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
ShoppingCart cart = context.getBean(ShoppingCart.class);
cart.checkout("CANCELLED");
}
}
BeanConfig.java
package org.example;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
#Configuration // Indicates this is a configuration class
#ComponentScan(basePackages = "org.example") // Indicates where to find the components/beans
#EnableAspectJAutoProxy // Enables the AspectJ features in project
public class BeanConfig {
}
i am learning spring aspect and unsure why the pointcut expression is not working .
Since the within pointcut designator limits matching to join points of certain types, the problem is your pointcut expression is matching types within ShoppingCart because of .* in the end. If you remove those characters it should work.
#Pointcut("within(org.example.ShoppingCart)")
public void authenticationPointCut(){}
I have a rest controller contains many methods
#RestController
#RequestMapping("v1/test")
public class TestRestController {
...... 100 methods (GET, POST, PATCH, etc)
}
How can I know which method is being accessed without using print in each method?
Are there any ways to do that?
While you can use AOP tactics noted in the other answers to log the methods, there are better approaches if all you want to do is log all of the requests and responses for the endpoints those methods implement. There are a couple ways this can be done: Use Spring's CommonRequestLoggingFilter or write your own HandlerInterceptor. Here is a nice article on the first two options.
Using Aspect Oriented Programming with Spring:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Aspect
public class SpringAspect {
private static final Logger LOG = LoggerFactory.getLogger(SpringAspect.class);
#Before("execution(* sample.package.path.TestRestController.*(..))")
public void executedMethodsLogger(JoinPoint joinPoint) {
LOG.info("[ Executed method {} ]", joinPoint.toString());
}
}
You can use Spring AOP:
package com.example;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class ExampleAspect {
#Before("execution(* com.example.TestRestController(..)")
public void log(JoinPoint joinPoint) {
System.out.println("Executing :" + joinPoint.toString());
}
}
I am trying to understand how AspectJ works so I built this very simple example. I can execute x() from a web browser but applaud() never gets executed. Why? How can I get it executed (apart from calling it inside x())? I am trying to do all this without creating an xml.
My environment is Java, Spring, AspectJ, IntelliJ and Windows 10.
package hello;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#Aspect
#Configuration
#EnableAspectJAutoProxy
public class SomeClass {
#RequestMapping("/x")
#Pointcut("execution(* hello.SomeClass.x())")
public String x() {
System.out.println("in x");
return "<div><h1>Some content</h1></div>";
}
#After("hello.SomeClass.x()")
public void applaud() {
System.out.println("CLAPCLAPCLAPCLAPCLAP");
}
}
I am using AOP for the first time.
I have written the below AOP code which works fine when i use it to intercept a particular method.
Can somebody guide me - how I can set it up to intercept all methods in a certain package (com.test.model)?
Basically how to setup appcontext.xml.
Also, do i need to do something like below to call before calling each method?
AopClass aoptest = (AopClass) _applicationContext.getBean("AopClass");
aoptest.addCustomerAround("dummy");
Can somebody help?
Please let me if some more explanation is needed.
Below is my code:
Interface:
package com.test.model;
import org.springframework.beans.factory.annotation.Autowired;
public interface AopInterface {
#Autowired
void addCustomerAround(String name);
}
Class:
package com.test.model;
import com.test.model.AopInterface;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
#Component
public class AopClass implements AopInterface {
public void addCustomerAround(String name){
System.out.println("addCustomerAround() is running, args : " + name);
}
}
AOP:
package com.test.model;
import java.util.Arrays;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class TestAdvice{
#Around("execution(* com.test.model.AopInterface.addCustomerAround(..))")
public void testAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("testAdvice() is running!");
}
}
appcontext:
<!-- Aspect -->
<aop:aspectj-autoproxy />
<bean id="AopClass" class="com.test.model.AopClass" />
<bean id="TestAdvice" class="com.test.model.TestAdvice" />
Just put:
#Around("execution(* com.test.model..*.*(..))")
The format of an execution expression is:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
where only ret-type-pattern, name-pattern and param-pattern are required, so at least we need an expression like:
execution(ret-type-pattern name-pattern(param-pattern))
ret-type-pattern matches the return type, * for any
name-pattern matches the method name, you can use * as wildcard and .. to indicate sub-package
param-pattern matches the method parameters, (..) for any number of parameters
You can find more information here: 10. Aspect Oriented Programming with Spring, there are some useful examples.
All the classes in project are in com.aspect package.
The main Aspect :
#Aspect
public class MainAspect {
#Pointcut("within(com.aspect..*)")
public void standaloneLayer(){}
}
Another aspect for joinpoints having account object as argument:
#Aspect
public class AccountAspect {
#After("com.aspect.MainAspect.standaloneLayer() && args(account)")
public void pointCutForAccount(JoinPoint joinPoint, Account account){
}
}
Service layer class:
#Service
public class Customer {
public void setAccountBalance(Account account) {}
}
While running application I am getting below exception:
Caused by:
java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:317)
Crosscheck your code once more whether you have imported org.aopalliance.intercept.Joinpoint instead of org.aspectj.lang.JoinPoint
Note for AspectJ AOP you need to import org.aspectj.lang.JoinPoint.
In my case the reason was that I imported the wrong class. Make sure that the class you import is org.aspectj.lang.JoinPoint and not any thing else.
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class LoggingAspect {
#Before("allCircleMethods()")
public void LogginAdvice(JoinPoint joinpoint)
{
System.out.println("advice is run");
System.out.println(joinpoint.toString());
}
#Before("args(String)")
public void StringArguementMethods()
{
System.out.println("A method that takes String arguement has been called");
}
#Pointcut("execution(* get*())")
public void allgetters()
{}
#Pointcut("within(as.model.Circle)")
public void allCircleMethods()
{}
}
when i imported import org.aopalliance.intercept.Joinpoint; i got 0 ubound in poincut error , so i changed the import to org.aspect.lang.JoinPoint and my program ran successfully