Announcement Announcement Module
Collapse
No announcement yet.
Using custom annotations with Spring AOP Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Using custom annotations with Spring AOP

    I am developing a web application that uses Spring MVC, Spring Services and Spring AOP. As a part of that, there is a logging aspect using Spring AOP that has before, afterReturning and afterThrowing methods. Also, there are few custom method-level annotations such as @DoNotLog and @LogExceptionAsWarning that I want to use in the aspect to see if logging should be done and if an exception should be logged as a warning. I tried to check for these annotations at run time using isAnnotationPresent method on a "Method" object, but it does not work.

    It seems to me that as the objects generated by Spring are proxy objects and not the objects that I have coded, the annotations declared on these methods are lost during aspect weaving. However, the weird part is that, during logging, it does show entries for the classes that I have coded.

    Looking forward to advise.

  • #2
    Hi

    I think you should try to include your annotation in the pointcut definition itself. Since Spring 2.0 you can use the @AspectJ style to declare your aspects.

    Here is a someway contrived example, but hope it helps.

    I have an After Throwing Adivce which handles exceptions from the application and sends them via email to a receiver.

    Code:
    @Aspect
    public class MailNotificationAspect {
    	private Mailer mailer;
    
    	public void setMailer(Mailer mailer) {
    		this.mailer = mailer;
    	}
    	
    	@Pointcut("execution(* *.*(..)) && @within(com.trivadis.issuesmgmt.aop.Mail) && @annotation(m) ")
    	public void inApplication(Mail m) {}	
    
    	@AfterThrowing(pointcut="inApplication(m)",throwing="ex")
    	public void afterThrowingWithSubject(Exception ex, Mail m) throws Throwable {
    		mailer.send(ex, m.subject());
    	}
    }
    Here is a service which throws an exception if the paramter is null.

    Code:
    @Mail
    public class PersonMgmtServiceImpl implements PersonMgmtService 
    {
    ...
    	@Mail(subject="This is the test subject")
    	public void createPerson(Person person) throws ApplicationException {
    		if (person == null) {
    			throw new ApplicationException();
    		}
    		personDAO.save(person);
    	}
    ...
    With the annotation Mail on class level, I specify that a mail should be sent whenever a method in the class throws an exception and with the annotation on method level I can overwrite the subject being used in the mail message.

    the imporant part in the aspect above is the pointcut declaration:

    @Pointcut("execution(* *.*(..)) && @within(com.trivadis.issuesmgmt.aop.Mail) && @annotation(m) ")
    public void inApplication(Mail m) {}

    This reads as "all executions of any @Mail annotated methods where the declared type of the target object (the class) has an @Mail annotation".
    By using @annotation(m) I'm using the binding form and bind it as a parameter to the advice

    @AfterThrowing(pointcut="inApplication(m)",throwin g="ex")
    public void afterThrowingWithSubject(Exception ex, Mail m) throws Throwable {
    mailer.send(ex, m.subject());
    }

    Hope this helps.

    One last thing you need to be aware of. Annotations on methods are not inherited, so if your on class level, you won't see a method-level annotation defined in an interface.

    Comment

    Working...
    X