I want to create an annotation for sending timer metrics for my methods. I thought about doing something like that:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Timer {
}
And then I want to use AspectJ for doing the metrics collection logic as follows:
#Aspect
public class TimerAspect {
#Pointcut("#annotation(Timer)")
public void timerPointcut() {}
#Pointcut("execution(* com.mycompany.**.*(..))")
public void methodPointcut() {}
#Before("methodPointcut() && timerPointcut()")
public void startTimer() throws Throwable {
// start timer logic here
}
#After("methodPointcut() && timerPointcut()")
public void sendTimer() throws Throwable {
// stop timer and send metrics logic here
}
}
What I would like to understand, and I'm not sure how to benchmark it, is whether I have a performance penalty here when using this annotation.
The Spring AOP performance penalty is considerable because dynamic proxies are being used through which each call will be routed.
AspectJ performance is much better, the penalty is really small because no dynamic proxies are needed. You can use native AspectJ from within Spring as described in the Spring manual, chapter "Using AspectJ with Spring applications".
As described in my comments here, you need to be careful what you measure. For instance, it makes no sense to measure the additional time it takes to do the actual timekeeping and logging compared to the original application without any timekeeping/logging because if you would add those manually via scattered timekeeping/logging statements, the penalty would also exist. I am also reasoning about profiling aspects here.
If you want to measure the pure aspect penalty, maybe you could do it similar to my sample code here.
Related
We have several implementations that use the same code base but we want them to do different things: i.e. rest access, administration via rest, indexing, archiving, and queue based.
In our infrastructure build out we want certain things to be accessible but other things not to be, such as in our administration/rest/indexing and archiving we don't want to buildout threads to monitor and handle queue requests, or in our indexing and archiving we want those processes, but we don't want the rest or queue build out.
So, I was wondering if there is a way to "extend" #ConditionalOnExpression with like an #ConditionalOnRest that extends #ConditionalOnExpression so we don't have to include the expression on each Component/RestController which we may have to change in a bunch of places or could be screwed up because it is functionally compile time checked and DRY.
You can achieve this in two ways.
Custom Annotation
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#ConditionalOnExpression() // add your expression
public #interface ConditionalOnRest {
}
Custom Condition
class RestCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return // Your condition logic here
}
}
Then you use it as follows:
#Conditional(RestCondition.class)
I'm planning to handle logging in spring.
Few suggest to handle it via LoggingInterceptor and some suggest to use AOP cross cutting concerns
which one is the recommended or best practice to follow for enterprise applications?
Thanks.
Both approaches have there own benefits and shortcomings. Logging via LoggingInterceptor is better approach as It is a standard library provided by Java to handle logging, you can do custom logging also.
AOP is better appraoch when you want to implement logging on more granular level as on certain return values of functions or classes. e.g if you want to log request only when the returning value is null. you can do it using AOP as :
#AfterReturning(pointcut = "execution(* com.foo.bar..*.*(..))", returning =
"retVal")
public void logAfterMethod(JoinPoint joinPoint, Object retVal) {
...
}
You can also do logging on returning value using Logging Interceptor but you need to write another function for that. i-e
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object
arg3) throws Throwable {
log = LogFactory.getLog(arg3.getClass());
log.info("LOGGING IS: "+arg1.getName());
}
For production point of view AOP has performance overhead as you are adding overhead to execution of all your service calls. While Logging Intercept is just a class with normal execution cycle.
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(..))")
I'm currently thinking about how i handle my domain objects along with hibernate considering the following :
My model object are directly annotated with JPA annotation, no entity layer.
On some database heavy operation, i don't mind tuning my code so i take full advantages of the proxies, even if we can consider it as a leak of abstraction/implementation masking. Of course i prefer when i can do otherwise.
Because i don't have entity layer, i don't have a DAO layer, the entity manager is considerered itself as a DAO layer (related : I found JPA, or alike, don't encourage DAO pattern)
However i was thinking about improve what i'm doing know in order to reduce a bit the complexity, or at least, relocate that complexity in a place it fits better, like entity's related service. And maybe more abstract the fact that i'm using an ORM.
Here is a generic CRUD Service from which all my business service inherits. This code is to show you how things are done currently (annotation, logs remove for clarity) :
public void create(T entity) {
this.entityManager.persist(entity);
}
#Transactional(value = TxType.REQUIRED, rollbackOn=NumeroVersionException.class)
public void update(T entity) throws NumeroVersionException{
try{
this.entityManager.merge(entity);
}catch(OptimisticLockException ole){
throw new NumeroVersionException("for entity "+entity, ole);
}
}
public T read(int id) {
return this.entityManager.find(entityClass, id);
}
public void delete(int id) {
T entity = this.entityManager.getReference(entityClass, id);
this.entityManager.remove(entity);
// edit : removed null test thanks to #JBNizet
}
The problem with this kind of implementation, is that if i want to create an object, then use the advantages of the proxies i basically have to create it then refetch it. Of course the query may not hits the database but hits only hibernat's cache (not sure about it though). But that means i still have to not forget to refetch the proxy.
This mean i leak the fact that i'm using an ORM and proxies behind the scenes.
So i was thinking to change my interface to something like :
public T read(int id);
public T update(T t)throws NumeroVersionException;
public T create(T object);
public void delete(int id);
List<T> list();
Meaning once i pass an object to this layer, i will have to use the returned value.
And implements update specifically like :
public T update(T t){
if(!(t instanceof [Proxy class goes there])){
//+ check if it is a detached proxy
entityManager.merge(t);
}
}
Since merge hits the database every time called, for some operation involving just some 10ish entities this can be annoying i wouldn't call it in an update method with a proxy.
Of course I expect to have some edge cases where i'll need the entityManager to flush things and so on. But i think this would reduce significatively the current complexity of my code and isolate better the concerns.
What i'm trying in short is to relocate the ORM code within the service so i can hide the fact that i'm using an ORM and proxies and use the interface like i was using any other implementation without loosing the benefits of using an ORM.
The question is so :
Is that new design a good idea towards this idea ?
Did i miss anything about how to handle this properly ?
Note : Even though i'm talking about performance, my concern is also about isolation of concerns, maintenability, and easier usability for developers that aren't familiars with ORMs and Java which i work with.
Thanks to #JBNizet i'm seeing some thing more clearly :
I should use the value returned by merge() method.
A managed entity is not always a proxy.
I don't have to abstract the fact that i use managed entities, this will lead to complex and unefficient code
I choosed JPA i won't switch for it which is true unless rewriting the full model to stand for something based on non relationnal database.
So i'll just change my update method from the original code and i'll keep the rest.
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.