Spring pointcut involving ignoring a class - spring

I have a point cut for all classes in Spring AOP like
#Pointcut("execution(* com.company.app..*(..))")
Now I need to exclude a class say com.company.app.IgnoreClass.
Can someone please help me write the pointcut?

The Pointcut to exclude all methods in IgnoreClass would be:
#Pointcut("execution(* com.company.app..*(..)) && !execution(* com.company.app.IgnoreClass.*(..)) ")
Documentation about pointcuts expression here, also more related information on Spring AOP declaring pointcuts here.

Related

Spring AOP Exclude Some Classes

I'm using Spring AspectJ for logging method execution statistics, however, I want to exclude some classes and methods from this without changing the pointcut expression.
To exclude certain methods I created a custom annotation which I use to filter out. However I'm unable to do the same with classes.
Here is my aspect definition -
#Around("execution(* com.foo.bar.web.controller.*.*(..)) "
+ "&& !#annotation(com.foo.bar.util.NoLogging)")
public Object log(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// logging logic here
}
NoLogging is my custom annotation for excluding methods.
So how can I filter out certain classes without changing pointcut expression and without adding new advisors?
Okay so I found the solution - use #target PCD (pointcut designators) to filter out classes with specific annotation. In this case I already have the #NoLogging annotation so I can use that. The updated pointcut expression will then become as follows -
#Around("execution(* com.foo.bar.web.controller.*.*(..)) "
+ "&& !#annotation(com.foo.bar.util.NoLogging)"
+ "&& !#target(com.foo.bar.util.NoLogging)")
public Object log(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// logging logic here
}
Explanation -
execution(* com.foo.bar.web.controller.*.*(..)) - all methods of all classes in c.f.b.w.controller package
"&& !#annotation(com.foo.bar.util.NoLogging)" - which do NOT have #NoLogging annotation on them
"&& !#target(com.foo.bar.util.NoLogging)" - and whose class also does NOT have #NoLogging annotation.
So now I simply have to add #NoLogging annotation to any class whose methods I want to be excluded from the aspect.
More PCD can be found in Spring AOP documentation - http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-pointcuts-designators
As per Spring AOP documentation
PCD can be &&'ed, ||'ed, and ! (negated) too.
So I guess this is more of trial and error exercise. I think you can try something like && !#within #within is applicable for types. Or you can try !#target
But then again I think it could be tricky.
Another approach: declare two pointcut definitions and combine them. And example, here on the documentation page. I would try this first. Something like
#Pointcut(executionPC() && nonAnnotatedClassesPC() && nonAnnotatedMethodsPC())
Disclaimer: As I said, this looks more like trial and error. And I don't have a clear working example.

How to write a advice which will inject for all the DAO classes which is annotated with #Repository

When I tried to find the answer for "difference between #component,#service,#Repository,#controller" I found one additional answer "It will help in case of AOP when you separate the layers by using these annotation.
For example if you want to inject one Aspect of logging (before,after)to all the DAO,you are able to do that using AOP as you have three distinct Layers and are not mixed.
Can anyone please suggest me the sample code how to write join points which will apply to all #Repository by using this annotation.I know how to create joint points with the help of expressions,autoproxycreater(which will tell inject advice whose method matches the advisor's pointcut) but how we will tell to inject advice to all the classes which is annotated with #Repository.
The following pointcut expression to advice based on annotation #target(org.springframework.stereotype.Repository) should help.

Spring pointcut XML expression on custom annotation

I have a custom annotation as follows:
#Inherited
#Target({ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface MyCustomAnnotation {
}
In Spring XML configuration I have the following:
<aop:pointcut id="fooPointcut" expression="#annotation(com.foo.blah.MyCustomAnnotation)"/>
This will only match on method annotations. How do I tweak the spel to also capture type/class annotations?
Use #within(com.foo.blah.MyCustomAnnotation) to
limit matching to join points within types that have the given annotation
A combined pointcut expression would become:
#annotation(com.foo.blah.MyCustomAnnotation) || #within(com.foo.blah.MyCustomAnnotation)
See Join Point Matching based on Annotations in the AspectJ 5 Developer's Notebook for further reference. Also note, that Spring's AOP doesn't support full AspectJ pointcuts, only a limited subset.
Also note that #annotation(com.foo.blah.MyCustomAnnotation) in AspectJ would match
all join points where the subject of the join point has the given annotation
meaning that it would match method-execution as well as method-call. In Spring AOP it only matches method-execution though, but it's better to write pointcut expressions that are valid in a broader scope as well, so don't forget to use an execution(...) pointcut too to restrict the pointcut.

while the pointcut be apply to bean ctor and all get/set property methods?

I have a Spring AOP pointcut execution(* someService.*(..)).
Will this pointcut match constructor and bean get/set property methods?
THIS is not my intention, and also maybe this behaviour will hurt performance.
I just want to advise REAL service methods, such us getUserByID etc.
How do I exclude those methods (get/set/constructor)?
That pointcut will match public methods in Spring AOP. So getters and setters, but not constructors.
The Spring reference for this is here. Section 8.2.3, look for "even constructors".
A clean way to only reference a group of methods is to apply the pointcut to an interface implemented by your service, instead of the service itself. This assumes your interface only contains business methods you want to advise.
in case it's a third party library and you don't want to use a marker interface for some reason, you can always base yourself on naming conventions of the methods. For example this applies the aspect to getters only:
execution(* someService.get*(..))
this expression applies the aspect to both getters and setters:
execution(* someService.get*(..)) && execution(* someService.set*(..))

Is the following pointcut valid?

I came across the following Spring AOP pointcut in a tutorial:
execution(public * * (..))
it was said that it would cause the execution of all public methods. Is that correct? AFAIK we can only intercept public methods, and that public keyword there is even illegal.
In addition to #Mario's answer, the spring docs on AOP say the following (emphasis mine):
Note Due to the proxy-based nature of Spring's AOP framework,
protected methods are by definition not intercepted, neither for JDK
proxies (where this isn't applicable) nor for CGLIB proxies (where
this is technically possible but not recommendable for AOP purposes).
As a consequence, any given pointcut will be matched against public
methods only!
If your interception needs include protected/private methods or even
constructors, consider the use of Spring-driven native AspectJ weaving
instead of Spring's proxy-based AOP framework. This constitutes a
different mode of AOP usage with different characteristics, so be sure
to make yourself familiar with weaving first before making a decision.
In addition, the pointcut grammer is as follows:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?
name-pattern(param-pattern) throws-pattern?)
Wherby the modifier-pattern would be public,protected etc but is optional...
Yes, it seems to be a valid pointcut, and it does exactly what he says.
In addition, it is worth to note that replacing the "public" keyword with "protected" is perfectly legal and it still works! Strangely it works also with "private" methods...
(Tested with Spring 3.1.2 + AspectJ 1.6.9)
As far as I know, CGLib proxies can be used to proxy protected methods, however they are effective only if they are invoked from a different object instance. So technically, it should be possible to advice protected methods exactly in the same way as public ones.
(As reported by #beny23 advicing protected/private methods does not work with Spring AOP proxy implementation, but only with Spring driven AspectJ weaving)
pointcut: designator(modifier returnType package.type.method(params))
in your case
execution(public * * (..))
would execute for all public methods with ANY return type in the project dir with 0 to many parameters

Resources