0

I want to listen on method calls in order to attach additional behavior dynamically around the call. I've already done it on JUnit methods with a custom annotation and runner. I'm trying to do it on a standard java application.

The main idea is to do:

@Override
public void beforeInvoke (Object self, Method m, Object[] args){
   Object[] newargs = modifyArgs (args);
   m.invoke (self, newargs);
}

It's just an abstract idea, I don't have any concrete example, but I'm curious if it's possible in java.

I've found some approaches:

java.lang.reflect.Proxy.newProxyInstance(...) 

where a proxy is defined for an interface only (but not used to decorate concrete classes). It seems similar to injection pattern and it's a different concern.

Another approach here using a factory pattern with the ProxyFactory class. This other solution requires explicit calls to create() method to produce object proxies listening on method invocations. So, if you bypass it by using natural constructors of your classes, it's not working. It's very constraining if you must explicit a call to a factory each time you have to create an object.

There is a way to do it with transparency ? Like Proxy.newProxyInstance() but working also on concrete classes ?

Thanks.

4
  • I'm assuming you're doing this just because you want to learn how to do this instead of using already existing frameworks like AspectJ for example? I'd suggest downloading the AspectJ sources and investigating how they did it. Commented Apr 9, 2015 at 13:24
  • Yeah I know AspectJ but I like coding my own frameworks (for personal use) to master and understand the underlying technical aspects. Moreover, it needs a specific environment. Commented Apr 9, 2015 at 13:42
  • ... where a proxy is defined for an interface only ... - Not true - the proxy you get can be used to wrap a concrete object and make it implement a specific interface. See here for a use case. Commented Apr 9, 2015 at 14:05
  • For my purposes, I see a drawback. Proxy/Adapter must be used each time you create an object to wrap it. Since a constructor cannot return a proxy instead of "this" you cannot ensure that no one bypass create method by calling constructors directly. (unless setting default visibility constructors, all classes in the same package with the proxy factory). Commented Apr 9, 2015 at 15:03

3 Answers 3

1

Well,this is commonly seen with Spring Framework and Aspect Oriented Programming. Since you delegate your constructor calls to Spring, it is quite easy for Spring to put a proxy in place to intercept calls to the actual objects.

As far as I can tell, the only way to intercept calls is to use a proxy. Either in the way you mentioned or using Spring and AOP.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I will study this framework. I hope I will not have to depend on huge libraries.
1

I think cglib let you instrument concrete classes.

5 Comments

It could be interesting but It seems to be a huge framework using code transformation. Maybe heavy just for intercepting method calls.
Yes. ASM (that is used by cglib) is lighter. You would need to know the the bytecode instructions though.forge.ow2.org/projects/asm
Thanks. However, it's very low level code manipulation. My objective is to ease coding by using some high levels artifacts. If I use a very low level framework manipulating bytecode its just counterproductive, in my opinion.
It seems similar (injecting source code at runtime) and a very low level approach. It provides also ProxyFactory class I mentionned above, but it consists in a wrapper object used by an explicit call to a create() function instead of natural constructors, so it's not really transparent. But, I will opt for this simple pattern if I don't find any high level solution.
I've found Enhancer also (from CGLIB) but it's the same problem. You have to explicit a call to create() method. It cannot be used on existing objects.
1

As far as I know there is no easy way to intercept method calls that are called on a concrete class. As mentioned you could manipulate the bytecode during compilation (as Used in AOP) or at class loading time (as used from cglib). Another product to instrument Classes would be jmockit (http://jmockit.org/). Usually I would use this special kind of black magic only in testing environments and not in an productive environment.

Another way you could go is Annotation Processing. It work's during compiling process. You have to write a Processor which will walk through your source code and generate source-code that contains the original code plus the enhanced method-calls you need. Depending on how much source-code you have to enhance, this method might be a good idea, but in general it is a lot of work. Here's a link (https://deors.wordpress.com/2011/10/08/annotation-processors/). Despite usually it's used in combination with annotations, this is not a strict requirement.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.