build: 309
updated: Jun 17 2008 Jodd Library
Community
Project Reports
Jodd
Jodd-WOT
|
Proxetta
* Never do that by proxy which you can do yourself. (Italian Proverb)
Table of Contents
Proxetta is all about dynamic proxies. Using just Java. In the same way you would code it by yourself. And the only dependency is Jodd & Asm library. Highlights
Dynamic Proxy
Sorry, documentation is not yet complete and does not provide sufficient information. Please refer to test cases, javadoc and sources for more details.
If you need more info on this particular subject, do not hesitate to demand more documentation. A dynamic proxy class is a class that wraps target class specified at runtime. Proxy Aspect contains advice and pointcut rules for applying advice. Proxy Advice is the code portion of an aspect, i.e. the logic that replaces crosscutting concern. Pointcut is a set of points in the application where advice should be applied, i.e. which methods will be wrapped by proxy. In Jodd, proxy is defined by its apsects that might be applied on target methods of target class. If pointcuts match one or more target methods, Proxetta will subclass the target class and override each target method with method that contains advice's code. Proxetta pointcuts are defined in pure Java, no custom language or XMLs is used, although user might easily extend this. For an example, let's create proxy over all methods that has been annotated with custom annotation: Pointcut
ProxyPointcut pointcut = new ProxyPointcut() { public boolean apply(MethodSignature msign) { List<AnnotationData> anns = msign.getAnnotations(); for (AnnotationData a : anns) { if (a.declaration.equals(Log.class.getName())) { return true; } } return false; } };
Attention! Advice
Here comes the fun and unusual part! Advices implement the Lets see this on example: public class LogProxyAdvice implements ProxyAdvice { public Object execute() { int totalArgs = ProxyTarget.argumentsCount(); Class target = ProxyTarget.targetClass(); String methodName = ProxyTarget.targetMethodName(); System.out.println(">>>" + target.getSimpleName() + '#' + methodName + ':' + totalArgs); Object result = ProxyTarget.invoke(); System.out.println("<<<" + result); return result; } } To emphasize: One should not to forget that Proxetta copies advice's constructors, static initialization blocks, fields, etc. Advices should be written carefully, always having in mind that advice's code will be added to the target classes. Common mistake might be accessing package scoped classes from advice, or using static attributes forgetting that this attribute will be copied to all target classes (simply use external class for that). For now, using inner classes in advices is not supported. Proxy
Proxy is defined very simply, not much to say about: ProxyAspect aspect = new ProxyAspect(LogProxyAdvice.class, pointcut); Working with Proxetta
Let's see now how all this works together. byte[] fooBytes = Proxetta.withAspects(aspect).createProxy(Foo.class); Class fooClass = ClassLoaderUtil.defineClass(fooBytes); or, at once: Class fooClass = Proxetta.withAspects(aspect).defineProxy(Foo.class); or, an instance: Foo foo = Proxetta.withAspects(aspect).createProxyInstance(Foo.class); These are just basic Proxetta usages. It is possible to provide target class as a string name, or input stream. Moreover, by default, creating proxy on target class still doesn't means that proxy will be created for class methods - if class has no valid pointcuts it will be remain untouched. Of course, this is configurable. Moreover, it is possible to turn on variable proxy class names, so proxy may be created several times and loaded by same class loader. And so on. How fast is Proxetta?
Due to unique approach that does not use reflection but macro-methods, Proxetta becomes very fast. For example, we took cglib library and created simple proxy (with help of dynaop project). Than in a simple big loop we just invoke proxified method that has single argument. While cglib version took cca 50 seconds, Proxetta needed only 13 seconds. Of course, using reflection in Proxetta will slows things down, but due to unique approach, many use-cases would not required reflection at all. Use Proxetta transparently with Petite
Petite container allows an easy way to "hook" on bean registration, where we can use Proxetta to modify the bean type and use enhanced type instead. More details and an example can be found on Petite page. |