Why does Spring AOP intercept protected methods under certain circumstances? - spring

I read that Spring AOP cannot intercept private and protected methods but it is intercepting them in a weird way why is that?
I have these functions i want to intercept:
public String getName(String string) {
System.out.println("Name : " + name + string);
return name;
}
protected String getNamesprotected(String string) {
System.out.println("Name : " + name + string);
return name;
}
This is my #Aspect code:
#Aspect
public class Logging {
#Before("execution(* com.tutorialspoint.Student.*Name*(..))")
public void beforeAdvice(JoinPoint joinPoint){
System.out.println("Going to setup student profile."+joinPoint.getSignature().toString());
}
}
When this code is executed both getName and getNamesprotected are intercepted but when I execute this code :
#Aspect
public class Logging {
#Before("execution(* com.tutorialspoint.Student.getNamesprotected(..))")
public void beforeAdvice1(JoinPoint joinPoint){
System.out.println("Going to setup student profile."+joinPoint.getSignature().toString());
}
}
Then nothing is intercepted. I also tried replacing getNamesprotected with *getNamesprotected* but still it does not intercept. It only intercepts when *Name* is there.
Can anyone explain me why this is happening?

Because the OP (Prateek Gupta) seemed to be unable (rather unwilling) to create a little SSCCE reproducing the problem and I was just bored during a tea break, I quickly created one by myself with Spring Boot and was very surprised that indeed Spring AOP, in contradiction to the documentation, at least under certain circumstance matches against protected methods when CGLIB proxies are involved.
Thus, I registered myself an account for Spring's Jira issue tracker and reported this regression as SPR-15354. You might want to subscribe for updates on that ticket if interested in answers by the Spring development team.
Update: The person answering to my ticket told me that this is a documentation issue. As SPR-1611 from 2006 tells us, this was already changed on purpose for Spring 1.2.7 but has never found its way into the documentation. Bottom line: Protected methods can be captured via Spring AOP, it is not an accident but has been undocumented for 12 years.
Update 2: The updated documentation text will be in the next Spring release. If you want to read the fixed text today, it is quoted in SPR-1611.

Can anyone explain me why this is happening?
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.
When this code is executed both getName and getNamesprotected are
intercepted
#Before("execution(* com.tutorialspoint.Student.*Name*(..))")
Here the preceding wildcard matches methods with any modifier (public, protected, and private) and any return type. The two dots in the argument list match any number of arguments.
Try this it should execute your protected method
#Pointcut("execution(protected * *.*(..))")
Also you can try this if it works for you (I am not 100% sure)
#Before("execution(* com.tutorialspoint.Student+.getNamesprotected(..))")

Related

Using AspectJ LTW to allow spring proxy functionalty on self-invocation of non-public methods and related considerations

I have seen numerous examples of Spring functionality related to #Cacheable, #Transactional, #Async, etc. where the same options are reiterated every time:
Self invocation made through a proxy object gotten through either the ApplicationContext.getBean(MyService.class) or an autowired MyService.class proxy object in addition to #Scope(proxyMode=ScopedProxyMode.TARGET_CLASS),
Relocating the target method to a separate #Service class,
Using AspectJ load-time weaving.
While the first two approaches are usually fine, there are times when we need to attach the functionality of the above three (and other) annotations to private methods, whether it be for code clarity, design, or other reasons.
There are many example of the first two approaches, but very few of the last. As I understand, due to the nature of AspectJ LTW, by default it is mutually exclusive with the usual Spring AOP behaviour that enables the #Cacheable, etc. behaviour without much hassle. My questions are as follows:
Are there any decent examples on enabling the above behaviour usually done with the first two options using AspectJ LTW?
Is there a way to enable AspectJ LTW selectively, e.g. not for #Async and #Transactional but just #Cacheable? An example use case of this would perhaps be: due to a team's design, all cacheable methods (some of which may be private) should be located in a facade class which calls private methods that perform heavy calculations, but might update some state (i.e. 'last-queried-at: #') before returning to the external called.
This question is from the viewpoint of a spring-boot user, but I believe it applies generally to Spring AOP and AspectJ LTW. Please correct me if there are special considerations needed in this case.
Are there any decent examples on enabling the above behavior usually done with the first two options using AspectJ LTW?
I have a couple of AspectJ examples on my GitHub account. Both these examples show how to intercept calls within the same target object (self-invocation) and also intercept private methods.
Spring Boot Source Weaving Example with AspectJ
Spring Boot Load-Time Weaving Example with AspectJ
Both the examples are similar except the way aspects are woven into target classes.
Please read the examples' READMEs to find out more about each type of weaving and on how to use each of the examples.
Is there a way to enable AspectJ LTW selectively, e.g. not for #Async and #Transactional but just #Cacheable?
Yes, you can filter based on either of the following:
By the annotation type of the caller method.
#Before("call(* com.basaki.service.UselessService.sayHello(..))" +
" && cflow(#annotation(trx))")
public void inspectMethod(JoinPoint jp,
JoinPoint.EnclosingStaticPart esjp, Transactional trx) {
log.info(
"Entering FilterCallerAnnotationAspect.inspectMethod() in class "
+ jp.getSignature().getDeclaringTypeName()
+ " - method: " + jp.getSignature().getName());
}
By the name of the caller method.
#Before("call(* com.basaki.service.UselessService.sayHello(..))" +
" && cflow(execution(* com.basaki.service.BookService.read(..)))")
public void inspectMethod(JoinPoint jp,
JoinPoint.EnclosingStaticPart esjp) {
log.info(
"Entering FilterCallerMethodAspect.inspectMethod() in class "
+ jp.getSignature().getDeclaringTypeName()
+ " - method: " + jp.getSignature().getName());
}
You can find working examples here.
Updated
Q. Do I understand correctly then, that if I wanted to enable compile-time weaving for transactionality, I would: 1. No longer use a TransactionAwareDataSourceProxy anywhere in my DataSource configuration; 2. Add the following to my application: #EnableTransactionManagement(mode=AdviceMode.ASPECTJ).
Spring AOP and CTW/LTW AspectJ weavings are completely orthogonal, i.e., they are independent of each other.
The compile and LTW modify the actual bytecode, i.e, the lines of code are inserted in the target object's method body.
AOP is proxy-based, i.e. there is a wrapper around the target object. Any call to the target object gets intercepted by the Spring wrapper object. You can also use Spring AOP with CTW/LTW if the need arises. In this case, Spring AOP will make a proxy of the modified target.
You will need #EnableTransactionManagement if you want to enable Spring's annotation-driven transaction management capability.
Q. In your examples, I see that you do not start the application in any special way for CTW. Would this suffice, or have I missed anything?
Yes, in CTW you don't need anything special during start-up since the extra bytecode is already injected in the original code by the AspectJ compiler (ajc) during compile time. For example, here is the original source code:
#CustomAnnotation(description = "Validates book request.")
private Book validateRequest(BookRequest request) {
log.info("Validating book request!");
Assert.notNull(request, "Book request cannot be empty!");
Assert.notNull(request.getTitle(), "Book title cannot be missing!");
Assert.notNull(request.getAuthor(), "Book author cannot be missing!");
Book entity = new Book();
entity.setTitle(request.getTitle());
entity.setAuthor(request.getAuthor());
return entity;
}
Here is the same piece of code after compilation by AspectJ compiler, ajc:
private Book validateRequest(BookRequest request) {
JoinPoint var3 = Factory.makeJP(ajc$tjp_0, this, this, request);
CustomAnnotationAspect var10000 = CustomAnnotationAspect.aspectOf();
Annotation var10002 = ajc$anno$0;
if (ajc$anno$0 == null) {
var10002 = ajc$anno$0 = BookService.class.getDeclaredMethod("validateRequest", BookRequest.class).getAnnotation(CustomAnnotation.class);
}
var10000.inspectMethod(var3, (CustomAnnotation)var10002);
log.info("Validating book request!");
Assert.notNull(request, "Book request cannot be empty!");
Assert.notNull(request.getTitle(), "Book title cannot be missing!");
Assert.notNull(request.getAuthor(), "Book author cannot be missing!");
Book entity = new Book();
entity.setTitle(request.getTitle());
entity.setAuthor(request.getAuthor());
return entity;
}
While in LTW, you need the Java Agent since the code gets modified during load-time, i.e., when the classes are being loaded by Java class loaders.

AspectJ pointcut on method in Spring CrudRepository

I'm using Spring's CrudRepository in combination with the annotation #RepositoryRestResource to implement a simple CRUD-app that can be used throught a RESTful API. I now want to add an AspectJ pointcut on my repository, so that some functionalities will be executed whenever a CRUD-method from the interface is called.
First, I extend Spring's CrudRepository to add some custom functionalities in my own interface:
#RepositoryRestResource(collectionResourceRel = "customers", path = "customers")
public interface CustomerRestRepository extends CrudRepository<Customer, Integer>{
Customer findOneByGuid(#Param("customerGuid") String customerGuid);
//Other custom methods.
}
Everything is working fine and I'm able to call this method via my REST client. I do not have to implement the interface CustomerRestRepository since Spring is doing the job as a miracle in behind. This is one of the crucial advantages of extending Springs's CrudRepository.
The problem, I'm facing now, is to add an AspectJ pointcut on this custom method findOneByGuid() that will, for example, log every call of the method after it's execution.
What I've tried by so far is:
#Aspect
public aspect AfterCustomerCrudAspect {
#Pointcut(
"execution(* com.x.y.z.CustomerRestRepository.findOneByGuid(..))")
public void customerCrudMethod() {}
#AfterReturning("customerCrudMethod()")
public void doSomething() {
//Do something
}
}
I've also tried:
1) execution(* com.x.y.z.CustomerRestRepository+.findOneByGuid(..))
2) execution(* org.springframework.data.repository.Repository+.*(..))
3) within(com.x.y.z.CustomerRestRepository)
4) annotation(RepositoryRestResource)
...and many others I do not remember. All with the same frustrating result: The advice is never applied.
By the way, I do not face any exceptions and if I try execution(* *.*(..)), the advice is working well - but, of course, not limited to the method findOneByGuid(). Thus, I think my code is correct in general.
I know that it is not possible to set pointcuts on interfaces. But since I do not have to implement the interface CustomerRestRepository by my own to get things working, I need to find a way to set a pointcut on an interface's method - or to find some other solution.
Well, one possible solution to that would be to implement the interface CustomerRestRepository. But then I've to do all the implementation work for the repository by my own and skip using the advantages of Spring's CrudRepository.
Thus, my question is, if there is a possibility to set a AspectJ pointcut on methods in a Spring CrudRepository.
Many thanks in advance for all the answers.
Well, I solved my problem in a different way.
Sometimes, things are less complicated than expected. Adding an AspectJ pointcut on a Spring CRUD-repository to execute some functionalities, whenever an entity is changed was not the best idea. (And at the best of my knowledge, it is not possible at all.)
There is a much more easier way to implement my requirement: The package javax.persistence provides the annotation #EntityListeners that suites perfectly to this job. So, annotate the entity class with the listener and implement the needed functionalities within the listener class:
#Entity
#EntityListeners(CustomerEntityListener.class)
//#Table, #NamedQueries and other stuff ...
public class Customer implements Serializable {
...
}
Implementation of the EntityListener:
public class CustomerEntityListener {
#PostPersist
public void customerPostPersist(Customer customer) {
//Add functionalities
}
}
The EntityListeneralso provides annotation for #PostUpdate, #PostRemove and so on - visit this site for more information.

Spring AOP Capturing of logs inside a method

I'm newbie to Spring AOP. I do understand the concept behind it and i also do understand the concept of #Before or #After etc usage. What i am so confused is still the usage of Spring AOP. Think of the below method of a class.
public void test(int x) {
:
x++;
logger.info("This is a test" + x);
:
try {
:
} catch (Exception e) {
throw new ...
}
:
}
The old way of capturing the log is as shown above.
Here's my questions:
If i were to implement the above method using Spring AOP, this logger will be removed but then does Spring AOP able to capture this log message? (from what i know Spring AOP does not look inside a method)
If answer to clause 1) is yes then how is it done?
If answer is no what's the point of using Spring AOP. Usage of #Before is useless unless you want to capture the information like parameters prior to execution of the method. Most of the time we want to capture some log inside a method itself.
Forget about AspectJ. I do know that AspectJ can do the above job.
I just want to know what's the point of using Spring AOP if it cannot do the very fundamental thing of capturing logs inside a method.
Any help is appreciated.
Further note:
I assume after implementating Spring AOP the above code would be like this. The logger call is no longer in the test method since it will be taken care of by the aspect class. Isn't that the purpose of AOP? To remove cross cutting concern from objects (since it's not related to the actual service of the object) and be taken care of by the aspect class?
public void test() {
:
try {
:
} catch (Exception e) {
throw new ...
}
:
}
If Spring AOP cannot do this what's the point of having a AOP?
I am having difficulty understanding what you are asking for here. In general, I don't know what it means to 'capture logs inside a method', but I think I can provide some assistance anyways.
It sounds to me like you want to arbitrarily insert code into random points in a method, not necessarily at the beginning or the end of the method. In general, Spring AOP cannot do this, and I am not sure that AspectJ will be able to help with either, but I am less familiar with that to give you a definitive answer.
Spring AOP, like you said, can inject before/after/around various JoinPoints in your codebase. These JoinPoints are going to be methods, and only in Spring managed classes.
So if you have a method like the following, you can add logging (via System.out in this case) around it via an #Around aspect.
The code:
public void test() {
System.out.println("I am in a method now");
}
The aspect:
#Around("execution(public * *(..))")
public void publicMethods(ProceedingJoinPoint pjp) {
System.out.println("before in an aspect");
pjp.proceed();
System.out.println("after in an aspect");
}
This essentially turns the initial method into this (as well as adding these System.out's to all public methods):
public void test() {
System.out.println("before in an aspect");
System.out.println("I am in a method now");
System.out.println("after in an aspect");
}
Depending on the layout of your code, you may be able to effectively insert arbitrarily by creating methods at the points that you want to insert. I wouldn't recommend this, but it certainly is possible.
Finally, here are the answers to your questions:
You could replace the logger with a #Before aspect, assuming the logging line is the first code in the method. If you were to do that, you would then be able to remove the logging from within the method. I don't quite know what you are asking for with the last sentence, but no, Spring AOP does not look 'inside' a method.
Spring AOP is able to 'capture' it because Spring will proxy the class.
The point of Spring AOP is to be able to 'intercept' method calls. You may not see a real use for it, but it is extremely useful. I would beg to differ on the last sentence, when using Spring AOP, I want to be able to examine what is going into my method, or what is coming out.
EDIT:
You are correct, the log call can be removed, and taken care of by the aspect. The thing that must be noted is that the only opportunities for the log method to be called by the aspect are either before or after the actual method invocation.

Load-Time-Weaving differences between aspectj-weaver and spring-weaver

I am having some strange problems using spring and Load-Time-Weaving using AspectJ.
In one of my Apsects, I wanted to react on invocations of the "doAuthentication" Method of the class org.springframework.flex.security3.SpringSecurityLoginCommand. Therefore I created a method:
#Around("execution(* org.springframework.flex.security3.SpringSecurityLoginCommand.doAuthentication(..))")
public Object aroundDoAuthentication(ProceedingJoinPoint pjp) throws Throwable {
...
This aspect is woven correctly if I use the aspectj-weaver agent, but is ignored if I use the spring-weaver. Unfortunately I have to use the spring-weaver, if I want correct aspect-spring integration. The only way I found out to get my aspect woven is to weave it around every method of the target class and to programatically filter the aspect calls:
#Around("execution(* org.springframework.flex.security3.SpringSecurityLoginCommand.*(..))")
public Object aroundDoAuthentication(ProceedingJoinPoint pjp) throws Throwable {
final String methodName = pjp.getSignature().getName();
if("doAuthentication".equals(methodName)) {
...
Using the above code, I managed to weave everythgin correctly, but I am not sattisfied with this as it seems to be a big hack to me.
Could anyone please explain why using the Spring-Weaver I am not able to weave the same as with the aspectj-weaver?
Chris
I don't know the code, but this seams to be the same old question.
Spring AOP is per default proxy based.
This means only invocations of methods that come from outside of the bean go though the proxy. Therefore only this invocation can trigger the AOP advice.

Can I inject code in spring using AOP annotations?

Is it possible to do something like the following:
public void doStuff(#RequirePrivilege("foo") User user) {
// ...
}
and have it effectively run as if it were the following?
public void doStuff(User user) {
if(!user.hasPrivilege("foo"))
throw new UserHasInsufficientPrivileges(); // this is a RuntimeException
// ...
}
I know that Spring has various sorts of AOP support, but the best I could find was AOP code which was annotated so that it would execute before or after a specific method. I want to do the inverse and annotate the code that should be changed.
Ultimately I could just do the above check inside the method, but the annotation way of doing things provides additional documentation which makes it obvious that the user requires a particular privilege without having to keep the documentation in sync with the code.
You can look at using AspectJ for doing this, as it will match on annotations. You can then use an around aspect to decide if the user meets the requirements to use this method.
Spring allows you to use AspectJ, and I would suggest that if possible you not do this at run-time, but at compile-time, as there is no reason to pay the price for using this aspect whenever you start the application. But, if you must do it at run-time then that is doable, to me I try to use compile-time as much as possible.
You may want to look at AspectJ In Action (http://www.manning.com/laddad2/) but here is an example from there:
Signature pattern:
* *(#RequestParam
(#Sensitive *))
Description
*Any method with one parameter marked with the #RequestParam annotations and the parameter’s type is marked with the #Sensitive annotation.*
Example
void create(#RequestParam
MedicalRecord mr), assuming
MedicalRecord carries the
#Sensitive annotation.
I'm certain that your "insufficient privileges" example can be done with Spring AOP, because that's how Spring Security works. You can do some very sophisticated things with around advice and AspectJ.

Resources