Community   SpringSource   Projects    Downloads    Documentation    Forums    Training   Exchange   Blogs

Go Back   Spring Community Forums > Core Spring Projects > AOP (Aspect Oriented Programming)

Reply
 
Thread Tools Display Modes
  #1  
Old Nov 12th, 2008, 06:09 PM
liamknox liamknox is offline
Junior Member
 
Join Date: Jun 2007
Location: Tokyo
Posts: 22
Default AOP Pointcuts and Parameter access

Hi

If I have methods that I want to point cut, for example

Code:
Entitled
void checkUser(X User user) 

Entitled 
void checkSomethingElse(X SomethingElse se, Y MoreSomethingElse mse)
Is the a way to declare say a single Aspect with Around advice and get accces to the paramater values and their associated annoation metadata?

Code:
Aspect(value="aroud("Entitled") && ???")
Thanks

Liam

PS CODE and HTML dont seem to work for At symbols
Reply With Quote
  #2  
Old Nov 13th, 2008, 03:36 AM
denis.zhdanov denis.zhdanov is offline
Senior Member
 
Join Date: May 2007
Location: Saint Petersburg, Russian Federation
Posts: 1,170
Default

6.2.4.6. Advice parameters
Reply With Quote
  #3  
Old Nov 13th, 2008, 05:00 AM
liamknox liamknox is offline
Junior Member
 
Join Date: Jun 2007
Location: Tokyo
Posts: 22
Default

Quote:
Originally Posted by denis.zhdanov View Post
This doesnt really answer my question. As far a I can see the examples here rely on you point cut having instrisic knowledge in the context of its use.
I.e. the parameters are passed in either using Arg names or specifying what exact Paramater level annotation you expect

In my example I am saying you are applying the same Aspect but to variable signatures. Sure you can get the parameter from the ProceedingJointPoint but there is no access to their metadata from what I can see unless you start reflecting, which seems wroing
Reply With Quote
  #4  
Old Nov 13th, 2008, 05:51 PM
liamknox liamknox is offline
Junior Member
 
Join Date: Jun 2007
Location: Tokyo
Posts: 22
Default

Hi Denis

I dont think this article answers my question exactly.
The examples here seem to inidicate that the Aspect knows instrisic information on the context it is applied i.e. the Annoations used at the parameter level or parameters names.

In my example I am assuming the declared Entitled annoation could be applied to any method and want to introspect the param data including their annotations. It is not obvious how this can be done. Sure from the pjp you can get the parameter values but you have no access to anything else. I would of thought the Parameter annotation meta data should be available as part of the StaticPart as it is really static data of the method after all ?

Thanks

Liam
Reply With Quote
  #5  
Old Nov 14th, 2008, 12:47 AM
liamknox liamknox is offline
Junior Member
 
Join Date: Jun 2007
Location: Tokyo
Posts: 22
Default

Actually this seems maybe more fundamental. There doest seem anyway of getting pased the annotation of a method parameter.

By this I mean using the annotation at the parameter level (ElementType.PARAMETER), and not TYPE , where you could match with args() etc.

Seems pretty big whole if you cant do this or get hold of the parameter annoatations from the JointPoint class ?
Reply With Quote
  #6  
Old Nov 14th, 2008, 01:58 AM
denis.zhdanov denis.zhdanov is offline
Senior Member
 
Join Date: May 2007
Location: Saint Petersburg, Russian Federation
Posts: 1,170
Default

Method arguments annotations are part of the method meta-information, hence, the only thing you should do is to get a method meta-information and derive static information about parameters annotations. Here is an example for @AspectJ style:

TestAnnotation.java
Code:
package com.spring.aop;

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}
AopService.java
Code:
package com.spring.aop;

import org.springframework.stereotype.Component;

@Component
public class AopService {

	public void service(@TestAnnotation Object o) {
		System.out.println("xxxxx: AopService.service()");
	}
}
TestAspect.java
Code:
package com.spring.aop;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class TestAspect {

	@Around("execution(* com.spring.aop.AopService.*(..))")
	public Object advice(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("xxxxxxxxxxxx: TestAspect.advice(): aspect is called on " + joinPoint
			+ ". This object: " + joinPoint.getThis());
		if (joinPoint.getSignature() instanceof MethodSignature) {
			MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
			Method method = methodSignature.getMethod();
			for (int i = 0; i < method.getParameterTypes().length; i++) {
				for (Annotation[] annotations : method.getParameterAnnotations()) {
					System.out.printf("Found the following static annotations at the parameter %d: %s%n",
						i, Arrays.toString(annotations));
				}
			}
		}
		return joinPoint.proceed();
	}
}
spring-config.xml
HTML Code:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">

	<context:component-scan base-package="com.spring.aop"/>
	<aop:aspectj-autoproxy proxy-target-class="true"/>

</beans>
SpringStart.java
Code:
package com.spring;

import com.spring.aop.AopService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringStart {
	public static void main(String[] args) throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
		AopService bean = (AopService)context.getBean("aopService");
		bean.service(new Object());
	}
}
Output:
Quote:
xxxxxxxxxxxx: TestAspect.advice(): aspect is called on org.springframework.aop.aspectj.MethodInvocationPr oceedingJoinPoint: execution(service). This object: com.spring.aop.AopService@12c5431
Found the following static annotations at the parameter 0: [@com.spring.aop.TestAnnotation()]
xxxxx: AopService.service()
It's little inconvenient to perform type cast there. The reason is that @AspectJ spring aop uses aspectj pointcut expression library. However, aspectj supports not only method join points (e.g. it supports fields access join points as well), hence, join point interfaces use generic signature interface and we need to perform type cast in order to obtain method meta-information.

It's possible to remove the cast by using pure spring advice style, i.e. perform the following change to the mentioned example:
  1. Introduce dedicated advice:

    TestAdvice.java
    Code:
    package com.spring.aop;
    
    import java.lang.reflect.Method;
    import java.lang.annotation.Annotation;
    import java.util.Arrays;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    public class TestAdvice implements MethodBeforeAdvice {
    
    	public void before(Method method, Object[] args, Object target) throws Throwable {
    		System.out.println("xxxxxxxxxxxx: TestAspect.advice(): aspect is called on " + method
    			+ ". This object: " + target);
    		for (int i = 0; i < method.getParameterTypes().length; i++) {
    			for (Annotation[] annotations : method.getParameterAnnotations()) {
    				System.out.printf("Found the following static annotations at the parameter %d: %s%n",
    					i, Arrays.toString(annotations));
    			}
    		}
    	}
    }
  2. Change spring config:

    spring-config.xml
    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
      http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
    
    	<context:component-scan base-package="com.spring.aop"/>
    
    	<bean id="advice" class="com.spring.aop.TestAdvice"/>
    
    	<aop:config>
    		<aop:advisor advice-ref="advice" pointcut="execution(* com.spring.aop.AopService.*(..))"/>
    	</aop:config>
    
    </beans>
You get the same result but without type casts.
Reply With Quote
  #7  
Old Nov 14th, 2008, 02:29 AM
liamknox liamknox is offline
Junior Member
 
Join Date: Jun 2007
Location: Tokyo
Posts: 22
Default

Thanks for your comprehensive reply. I actually found a similar article here.

Code:
http://www.nabble.com/Sring-AOP---ProceedingJoinPoint---Method-td20042019.html
Amazing how difficult that was and that its not in the Spring documentation
I would advise it should be mentioned as its seem as sensible thing to want todo.

The down cast is ugly but bareable. I am assuming the main requirement for this is due to the age of these libs (pre Java 5), as in makes perfect sence to expose the metadata yet restrict the access to method.

Perhaps in a later version we would see this encapsulation corrected.

Regards

Liam
Reply With Quote
  #8  
Old Nov 14th, 2008, 03:09 AM
denis.zhdanov denis.zhdanov is offline
Senior Member
 
Join Date: May 2007
Location: Saint Petersburg, Russian Federation
Posts: 1,170
Default

Quote:
Originally Posted by liamknox View Post
Thanks for your comprehensive reply.
Welcome.

Quote:
Originally Posted by liamknox View Post
Amazing how difficult that was and that its not in the Spring documentation
I would advise it should be mentioned as its seem as sensible thing to want todo.
The idea is straightforward - obtain Method object and derive necessary information from it. I don't see any difficulties with that.

Quote:
Originally Posted by liamknox View Post
The down cast is ugly but bareable. I am assuming the main requirement for this is due to the age of these libs (pre Java 5)
As I said, method information is not included to the general join point interface because aspectj supports join points over than method calls. It has nothing to do with java version.

Quote:
Originally Posted by liamknox View Post
in makes perfect sence to expose the metadata yet restrict the access to method.

Perhaps in a later version we would see this encapsulation corrected.
I'm afraid it's not clear what do you mean here. Both static information about join point and actual parameters are available at runtime. What kind of improvement do you want to see?
Reply With Quote
  #9  
Old Nov 14th, 2008, 06:14 PM
liamknox liamknox is offline
Junior Member
 
Join Date: Jun 2007
Location: Tokyo
Posts: 22
Default

if I have a method for example

Code:
getStaticPart()
Would you not expect it to provide the static information of the method?
It already provides, name, type etc

Obviously someone decided in the design of this API to favour not exposing the method. This sounds fair, if you just expose
Code:
pjp.prooceed()
you restrict abuse of parameters

However then they expose
Code:
pjp.proceed(args)
.
At which point you basically shoot youself in the foot really interms of why you didnt offer
Code:
pjp.getMethod()
I am sure there are other arguments, but basically the API looks out of touch with Java 5 and the ability to annotate. Any need to downcast like this should be taken as a fundamental failure in the API.
Reply With Quote
  #10  
Old Nov 14th, 2008, 06:23 PM
liamknox liamknox is offline
Junior Member
 
Join Date: Jun 2007
Location: Tokyo
Posts: 22
Default

On your reply regarding the difficulty.

Do you downcast Map to HashMap to access fundamentals? Is this need or requirement documented in the Java API....

No, because you dont have to

Are you basically saying it is obvious and GOOD to read an API and JavaDoc, see an interface, then consider what implementation could be behind it, so you can basically abuse the contract of this and make your code less portable

I really am not sure what you are getting at but its very non OO
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 02:47 AM.


Contegix provides first-class managed hosting and partial sponsorship of these forums.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.