Most Efficient Way to Invoke Methods at Runtime with a Specific Annotation - java

I have a class A with a bunch of methods I have annotated the same with unique Annotations. I want to invoke the method at runtime given the specific annotation. Also, I might have to pass parameters as well.
public class XYZAccessor(){
#CustomAnnotation(id="methodAIdentifier")
public String methodA(){
return "A";
}
#CustomAnnotation(id="methodBIdentifier")
public String methodB(){
return "B";
}
#CustomAnnotation(id="methodCIdentifier")
public int methodC(int param){
return (5+param);
}
}
Given the string "methodAIdentifier", I would like to invoke XYZAccessor.methodA();
I have seen these approaches for the same.
1) Java Reflection: XYZAccessor.getClass.getMethods.getAnnotations()
Iterate through that and find the specific method and invoke it.
2) Google Reflections: These have javaassist and guava as a dependancy.
Use their framework Class.getMethodAnnotatedWith("methodAIdentifier")
3) AspectJ: I am not clear on how to use Aspect for this use case. Something like a pointcut and an #Around. Something like
Pointcut matching methods with annotated parameters
Which of these approaches is the most efficient and the best approach to this problem?

Related

Annotation like #depreciated

I'd like to implement an annotation for methods which will let me know where those annotated methods called, just like official #deprecated annotation.
How can I get the list of all calling methods for a given annotated method?
I think this question may help you:
To find this annotated method (from Arthur Ronald's answer):
use
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
API
A component provider that scans the classpath from a base package. It then applies exclude and include filters to the resulting classes
to find candidates.
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(<DO_YOU_WANT_TO_USE_DEFALT_FILTER>);
scanner.addIncludeFilter(new AnnotationTypeFilter(<TYPE_YOUR_ANNOTATION_HERE>.class));
for (BeanDefinition bd : scanner.findCandidateComponents(<TYPE_YOUR_BASE_PACKAGE_HERE>))
System.out.println(bd.getBeanClassName());
Or (from Jonathan's answer):
Google reflections:
https://github.com/ronmamo/reflections
Quick review:
Spring solution is the way to go if you're using Spring. Otherwise it's a big dependency.
Using ASM directly is a bit cumbersome.
Using Java Assist directly is clunky too.
Annovention is super lightweight and convenient. No maven integration yet.
Google reflections pulls in Google collections. Indexes everything and then is super fast.
Update: If want to calling methods for a given annotated method, you should use AOP (Aspect Oriented Programming) and add # Around or # Before, for example something like this (I don't check this code):
public class Foo {
#YourAnnotation
public int power(int x, int p) {
return Math.pow(x, p);
}
}
#Aspect
public class MethodLogger {
#Around("execution(* *(..)) && #annotation(YourAnnotation)")
public Object around(ProceedingJoinPoint point) {
Logger.info(
"call by method" + MethodSignature.class.cast(point.getSignature()).getMethod().getName()
);
Object result = point.proceed();
return result;
}
}

Is it possible to use JMockit's Deencapsulation API to exchange method implementation?

So, basically, a there is some poor code that I cannot change that needs to be tested. Traditionally, you inject your mocked dependencies, but with this code, I cannot do so, because there are no setter methods. Worse, the function I need to test calls a bunch of static factory methods-I can't just use the MockUp strategy to swap out the implementation there, because there is no class instance to be injected at all.
In C/++, you can retrieve a pointer to a function and know it's type by it's signature. If you changed the pointer, then you could potentially change how the stack was constructed by the compiler and you could pass function's around and all that Jazz.
Is there a way to use the Deencapsulation API to replace a static method implementation? Using this, I could write my own class, descend from the traditional, but return mocked objects in order that dependency injection still be achieved?
public class TestedClass {
public static void testedMethod() {
UnMockableType instanceVariable =
UnInjectableFactory.staticFactoryConstructor();
instanceVariable.preventControlFlowInfluenceThroughMocking();
}
}
Easy enough:
#Test
public void exampleTestUsingAMockUp()
{
new MockUp<UnMockableType>() {
#Mock
void preventControlFlowInfluenceThroughMocking() {}
};
TestedClass.testedMethod();
}
Above, UnInjectableFactory isn't mocked because it doesn't need to be (assuming it simply instantiates/recovers an UnMockableType).
It could also be done with #Mocked and the Expectations API.

Extending Spring's pointcut-definig expression language

I am currently experimenting with Spring and its AOP features.
What I would like to know is if it is possible to extend the expression language of pointcut definition somehow...
I am quite familiar with the standard behaviour and usage of pointcut designators Spring provides but for my needs I would like to implement my own one.
Say we have a method in our aspect:
#Aspect
public class AspectClass {
#Before("execution(* *.get*(..)) && #annotation(someAnnotation)"
public void doStuff(ProceedingJoinPoint pjp, SomeAnnotation someAnnotation) {
System.out.println("Doing stuff!");
}
}
Now what I would like is something like this:
...
#Before("execution(* *.get*(..)) && #myAnnotation(someAnnotation)"
public void doStuff(ProceedingJoinPoint pjp, SomeAnnotation someAnnotation){
...
Where the myAnnotation(..) token is my custom extension of the expression language.
When I delved into Spring implementation I found where the parser resides and the fact it is hard-coded into AspectJExpressionPointcut implementation. Hence providing a custom implementation of said parser and sticking it someplace in some bean initialization routine seems like a no-no.
Exemplary usage of this extension would be for example matching a method by it's annotation, disregarding proximity of this annotation in the object hierarchy. So it would match a method that is overriden and whose annotation is defined on the parent's implementation.
public abstract class Superclass {
#SomeAnnotation
public abstract String getValue();
}
public class TheClass extends Superclass {
#Override
public String getValue() { // <- this would get advised by Spring using formerly defined aspect
// return some stuff
}
}
I know that I can reflect the method in the advice and check if the annotation is present on some method of some superclass, but I would like to encapsulate this process and offer it for convenient usage.
Have you guys stumbled upon something like this & can you offer me a solution (if it is possibe) / explanation (if it is not)? :-)
Thanks in advance, Janek.

Listening for when a method is called in a class, and then possibly overriding it (java)

So, let's say I have 2 classes, Foo1 and Foo2, which is in a separate library.
Foo2 is a class that is already instantiated, and I cannot correctly reinstintate it as a subclass to override a method in Foo2.
Is there any way I can listen to a certain method that is called in Foo2, and then possibly cancel the execution of said method, and from there create another method. I understand if what I"m saying is confusing, hopefully I can get some help :).
class Foo{
void x(){
if (Foo2.x2().called){
//do stuff
}
}
}
class Foo2{
void x2(){
//Stuff done here...
}
}
Obviously, the above code won't do anything, it is just simple an example of what I am looking for.
you need a proxy on that object, and an interceptor on the method. There are a couple of ways to do it:
If you have an interface you can use reflection and proxies and invocation handlers docs.oracle.com/javase/6/docs/api/java/lang/reflect/Proxy.html.
If you have a concrete class you can use CGLIB cglib.sourceforge.net to create an enhancer for your class
If you are using Spring you can use the AOP http://static.springsource.org/spring/docs/2.5.5/reference/aop.html.
You can also use AspectJ http://www.eclipse.org/aspectj/doc/next/progguide/ to do the same
Cheers!
If you can't somehow subclass Foo2 or modify the existing lib (in worst case you could decompile/modify/recompile) you could use aspectj to intercept calls.
You'd probably want to use load-time weaving for this purpose. Check out the general documentation for load-time weaving here: http://www.eclipse.org/aspectj/doc/next/devguide/ltw.html. It's a fairly involved procedure to add/configure aspectj though so I'd only recommend it as a last resort
Depending on what you're trying to do, this might work:
If you had a boolean isX2Called in class Foo, when x2() is called, set isX2Called to true. Then in x(), you can check if isX2Called is true. If you ever want to reset, you can set isX2Called back to false. This might not work for all purposes though.
In my opinion, to solve this issue you could use a third class to act as a Decorator/Proxy.
For instance, you can do something like:
class FooManager {
private Foo1 f1;
private Foo2 f2;
private boolean canExecuteFooMethods(){
// Evaluate if should run any Foo1 or Foo2 method
}
public void foo1Method(){
if(canExecuteFooMethods()){
f1.x();
}
}
public void foo2Method(){
if(canExecuteFooMethods()){
f2.x();
}
}
}
Assuming that you can subclass the type, the following code would work perfectly:
Foo foo = new Foo() {
#Override
public void someMethod() {
super.someMethod();
//your logic here (listen, hook, spy, override, etc)
}
}

Java - Register all classes annotated with #MyAnnotation

I have an annotation #MyAnnotation and I can annotate any type (class) with it. Then I have a class called AnnotatedClassRegister and I would like it to register all classes annotated with #MyAnnotation so I can access them later. And I'd like to register these classes automatically upon creation of the AnnotatedClassRegister if possible, and most importantly before the annotated classes are instantiated.
I have AspectJ and Guice at my disposal. The only solution I came up with so far is to use Guice to inject a singleton instance of the AnnotatedClassRegister to an aspect, which searches for all classes annotated with #MyAnnotation and it adds the code needed to register such class in its constructor. The downside of this solution is that I need to instantiate every annotated class in order for the code added by AOP to be actually run, therefore I cannot utilize lazy instantiation of these classes.
Simplified pseudo-code example of my solution:
// This is the class where annotated types are registered
public class AnnotatedClassRegister {
public void registerClass(Class<?> clz) {
...
}
}
// This is the aspect which adds registration code to constructors of annotated
// classes
public aspect AutomaticRegistrationAspect {
#Inject
AnnotatedClassRegister register;
pointcutWhichPicksConstructorsOfAnnotatedClasses(Object annotatedType) :
execution(/* Pointcut definition */) && args(this)
after(Object annotatedType) :
pointcutWhichPicksConstructorsOfAnnotatedClasses(annotatedType) {
// registering the class of object whose constructor was picked
// by the pointcut
register.registerClass(annotatedType.getClass())
}
}
What approach should I use to address this problem? Is there any simple way to get all such annotated classes in classpath via reflection so I wouldn't need to use AOP at all? Or any other solution?
Any ideas are much appreciated, thanks!
It's possible:
Get all paths in a classpath. Parse System.getProperties().getProperty("java.class.path", null) to get all paths.
Use ClassLoader.getResources(path) to get all resources and check for classes: http://snippets.dzone.com/posts/show/4831
It isn't simple that much is sure, but I'd do it in a Pure Java way:
Get your application's Jar location from the classpath
Create a JarFile object with this location, iterate over the entries
for every entry that ends with .class do a Class.forName() to get the Class object
read the annotation by reflection. If it's present, store the class in a List or Set
Aspects won't help you there, because aspects only work on code that's actually executed.
But annotation processing may be an Option, create a Processor that records all annotated classes and creates a class that provides a List of these classes
Well, if your AnnotatedClassRegister.registerClass() doesn't have to be called immediately at AnnotatedClassRegister creation time, but it could wait until a class is first instantiated, then I would consider using a Guice TypeListener, registered with a Matcher that checks if a class is annotated with #MyAnnotation.
That way, you don't need to search for all those classes, they will be registered just before being used. Note that this will work only for classes that get instantiated by Guice.
I would use the staticinitialization() pointcut in AspectJ and amend classes to your register as they are loaded, like so:
after() : staticinitialization(#MyAnnotation *) {
register.registerClass(thisJoinPointStaticPart.getSignature().getDeclaringType());
}
Piece of cake, very simple and elegant.
You can use the ClassGraph package like so:
Java:
try (ScanResult scanResult = new ClassGraph().enableAnnotationInfo().scan()) {
for (ClassInfo classInfo = scanResult.getClassesWithAnnotation(classOf[MyAnnotation].getName()) {
System.out.println(String.format("classInfo = %s", classInfo.getName()));
}
}
Scala:
Using(new ClassGraph().enableAnnotationInfo.scan) { scanResult =>
for (classInfo <- scanResult.getClassesWithAnnotation(classOf[MyAnnotation].getName).asScala) {
println(s"classInfo = ${classInfo.getName}")
}
}

Categories

Resources