can we have mutiple pointcuts mapped to a single advice - spring

In aspectj , can we have multiple pointcuts mapped to the single advice ?
for example below are two separate pointcuts
#Pointcut("execution(* xyz.get(..))")
void pointcut1() {
}
#Pointcut("execution(* abc.put(..))")
void pointcut2() {
}
so can anyone give idea how to configure these two pointcuts on a single advice ?
because for single pointcut to single advice like below we have
#Before("pointcut1()")
public void beforeLogging() {
System.out.println("Before Methods");
}
how to configure the same advice for multiple pointcuts ?

Yes, you can combine pointcuts with logical AND (&&) as well as logical OR(||) operators or negate them by logical NOT (!).
What you probably want here is this:
#Before("pointcut1() || pointcut2()")
The OR makes sense here because in your example a logical AND would always lead to an empty set: a method cannot be in two packages at the same time, but in one of them alternatively.

You can use the || operator.
From the docs http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/aop.html (9.2.2 Declaring an aspect):
#Pointcut("execution(public * (..))")
private void anyPublicOperation() {}
#Pointcut("within(com.xyz.someapp.trading..)")
private void inTrading() {}
#Pointcut("anyPublicOperation() || inTrading()")
private void tradingOperation() {}

Related

Why doesn't Spring support the order of annotations advice at the method level?

#Component
#Aspect
#Slf4j(topic = "e")
public class NotVeryUsefulAspect{
#Pointcut("within(com.lc.aop.for_source.service.impl.AAopServiceImpl)")
public void pointCutWithinAAopService(){
}
#Pointcut("#within(com.lc.aop.for_source.service.XAnnotation)")
public void pointCutAnnotation(){
}
#Before("pointCutWithinAAopService()")
#Order(0)
public void adviceBeforeAAopService(){
log.debug("=======before aop service========");
}
#Before("pointCutAnnotation()")
#Order(-1)
public void adviceBeforeAAopService2(){
log.debug("=======before aop annotation========");
}
}
#Slf4j(topic = "e")
#Component("a")
#XAnnotation
public class AAopServiceImpl implements AopService {
#Override
public void m() {
log.debug("a -AAopServiceImpl");
}
}
Based on the advice-ordering
Consider collapsing such advice methods into one advice method per join point in each #Aspect class or refactor the pieces of advice into separate #Aspect classes that you can order at the aspect level via Ordered or #Order.
Do I understand correctly that the #Order does not work in this case? Why not suport the method level order?
I think this is a very simple function, but it can avoid some unnecessary misunderstandings about #Order
I would like to order advice by method level.
Well, the answer to your question is in the sentence directly before the one you quoted, in the very same paragraph of the very same info box:
When two pieces of the same type of advice (for example, two #After advice methods) defined in the same #Aspect class both need to run at the same join point, the ordering is undefined (since there is no way to retrieve the source code declaration order through reflection for javac-compiled classes).
That question should probably be posed to the chaps working on the springframework, that project is located at: https://github.com/spring-projects/spring-framework.
What you're asking for makes sense, but keep in mind that Order is meant to prioritize the loading of beans from the context, so it makes sense that Order needs to be applied to the Aspect and not the Pointcut itself.

Creating default pointcut spring aop

While to utilise the AOP to authorize request in my controllers, I used the approach that
there is default validation and specfic validation, so that the request for which I don't have specfic pointcut defined they are authorized by the default approach.
#Before("execution(* com.example.controller.ExampleController.*(..))")
public void validate() {
validatePermissions("user", "create");
}
#Before("execution(* com.example.controller.*.*(..))")
public void validateUser() {
validatePermissions("admin", "admin");
}
Problem is that even though I have specfic validation defined for User case Its even in case of request to my Example controller request is always going to default one.
what I want is that only request not already covered by other pointcut should go to the default pointcut
You would make the specific pointcut(s) reusable and reference them in && !specificPointcut() conditions, roughly like this (untested, just written in the browser):
#Pointcut("execution(* com.example.controller.ExampleController.*(..))")
public void specificPointcut() {}
#Before("specificPointcut()")
public void validate() {
validatePermissions("user", "create");
}
#Before("execution(* com.example.controller.*.*(..)) && !specificPointcut()")
public void validateUser() {
validatePermissions("admin", "admin");
}
You can easily extend that to multiple specific pointcuts, either serially or hierarchically, depending on your situation.
Serially excluding pointcuts would work like && !(specificPc1() || specificPc2()) and hierarchically by a more common level always excluding the next more specific one.
From the reference documentation : Advice Ordering
When two pieces of the same type of advice (for example, two #After advice methods) defined in the same #Aspect class both need to run at the same join point, the ordering is undefined (since there is no way to retrieve the source code declaration order through reflection for javac-compiled classes). Consider collapsing such advice methods into one advice method per join point in each #Aspect class or refactor the pieces of advice into separate #Aspect classes that you can order at the aspect level via Ordered or #Order.
Considering the ordering is undefined and two different PCDs target the same join point , it is not possible to have a fallback or default pointcut among these two.
You could order the aspects after collapsing them to separate #Aspect classes , check the state of authorization ( may be from a thread local variable) or from an agrument you can get hold of from the join point.

How to match two patterns in one pointcut expression

I want to define my pointcut to match two kinds of methods:
all methods from class org.mypackage.Foo with names starting with "update"
all methods from the same class with names starting with "delete"
I tried the following:
#Before("execution (* org.mypackage.Foo.update*(..) ) && execution(* org.mypackage.Foo.delete*(..) )")
public void verify()
{
//verify if user has permission to modify...
}
It doesn't work. When I call either a Foo.update*() method or a Foo.delete*() method, verify() is not invoked.
How should I change it?
There are 2 option to match patterns in pointcut expression. The pointcut expression may be either a simple reference to a named pointcut, or a pointcut expression declared in place.
By creating individual method for respective point cut. And using that method name as reference in #Before advice.
#Pointcut("execution(* org.mypackage.Foo.update*(..))")
private void fooUpdate() {}
#Pointcut("execution(* org.mypackage.Foo.delete*(..))")
private void fooDelete() {}
#Before("fooUpdate() || fooDelete()")
public void verify() {
// verify if user has permission to modify...
}
Directly declaring pointcut expression in place.
#Before("execution(* org.mypackage.Foo.update*(..)) || execution(* org.mypackage.Foo.delete*(..))")
public void verify() {
// verify if user has permission to modify...
}
Change && to || in your expression.

Spring AOP: differences between && and 'and'

I have this interface:
public interface Performance {
public void perform();
}
Implemented by this class:
#Component
public class PerformanceImplementation implements Performance {
public void perform() {
System.out.println("PerformanceImplementation.perform()");
}
}
I want to apply the following aspect to the method of the interface above but only if the method is executed within another package, so I use the within designator using that package name
#Aspect
public class Audience {
#Pointcut("execution(** concert.Performance.perform(..)) " +
"and within(asdasdasd.*)")
public void performance() {}
#Around("performance()")
public void watchPerformance(ProceedingJoinPoint jp) {
try {
System.out.println("Silencing cell phones");
System.out.println("Taking seats");
jp.proceed();
System.out.println("CLAP CLAP CLAP!!!");
} catch (Throwable e) {
System.out.println("Demanding a refund");
} }
}
If I use and instead of && the aspect will be triggered anyway and it seems that it is not considering the limitation of the designator.
Is there any reason why this happens?
It depends whether you are using them inside annotation or xml .
Pointcut expressions can be combined using '&&', '||' and '!'
#Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {}
When combining pointcut sub-expressions, '&&' is awkward within an XML document, and so the keywords 'and', 'or' and 'not' can be used in place of '&&', '||' and '!' respectively. For example, the previous pointcut may be better written as:
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..)) **and** this(service)"/>

Dynamic pointcut expression in aspectj/spring aop

I want to create a pointcut expression which is dynamic in nature.
I have three packages -
package1,
package2,
common
common should always be inculded and based on system property i want to load package1 OR package2 at any given time
Something like below
private static final String PACKAGE = System.getProperty("packagePrefix");
#Around("execution(* "+PACKAGE+"..*.*(..)) && execution(* ..common.*(..))")
how can i achieve this?
EDIT:
I have found this which is quite interesting and i guess will solve my requirement but not able to get it working
So this link says to have like below
#Aspect
public abstract class MyAspect {
protected abstract pointcut();
#Before("pointcut()")
public void myAdviceMethod() {
// Advice code goes here
}
}
public class ConcreteAspect extends MyAspect {
#Pointcut("execution(* com.acme.*.*(..))")
protected pointcut() {
)
}
Included below in my Java config
#Bean
public ConcreteAspect myAspect() {
return new ConcreteAspect();
}
But getting below error :
java.lang.IllegalArgumentException: error at ::0 can't find referenced
pointcut pointcut
I guess at run time its not able to find out overriden pointcut method and hence not able to resolve pointcut.
Any idea how can I fix this?
You could use an if() clause to make a check like this:
aspect X {
before(): execution(* Code.*(..)) &&
if(isOfInterest(thisJoinPointStaticPart.getSignature().getDeclaringType())) {
System.out.println("advice running");
}
public static boolean isOfInterest(Class s) {
return s.getPackage().toString().startsWith(packagePrefix);
}
}
I think something similar will work for annotation style syntax. But this approach will include a runtime test at every matched join point.
You can use within, which will scan the given packages
#Pointcut("within(..common..(..)")
public void CommonPackage(){}
#Pointcut("within(..PACKAGE..(..)")
public void specificPackage(){}
And using #Around/#Before or any advice as u require for your situation
#Around("execution(CommonPackage()&&SpecificPackage()")
Writing the pointcut expression for the different packages and binding them together. Hope this helps!

Resources