Guice: Intercepting method with params and fields - java

Im looking into intercepting method invocations with Guice. I saw from here that basic interceptions are possible. However, the logic intercepting the methods require access to not only the parameters passed into the function, but also (unfortunately) a class member property. Is it possible to achieve this with Guice AOP? If so, what needs to be done? I'm thinking of something that might look like this:
class Foo {
#customInterceptor Object member; // Intercepting logic needs this
// function to be intercepted, param needed for the logic as well
#customInterceptor
void myFunc(#customInterceptor String param) {
// body, do something with member and param
}
}

It is possible using reflection. Not sure if it is a good practice and I assume you know what you are doing!
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Object o = methodInvocation.getThis();
Field f = methodInvocation.getMethod().getDeclaringClass().getDeclaredField("member");
//if member is private
f.setAccessible(true);
System.out.println("inside interception :: " + f.get(o));
f.setAccessible(false);
return methodInvocation.proceed();
}

Related

How to intercept method with ByteBuddy as in CGLIB with MethodInterceptor for calling MethodProxy.invokeSuper(...)

I want to intercept some methods with ByteBuddy.
When i use InvocationHandlerAdapter.of(invocationHandler) i can't invoke super method. Holding object instance is not suitable for my case. I want exactly as in CGLIB like below.
(MethodInterceptor)(obj, method, args, proxy)->{
// to do some work
Object o = proxy.invokeSuper(obj,args);
// to do some work
return o;
}
How can i achieve intercepting method in ByteBuddy like this?
I tried MethodCall type of Implemetation but it not solved my problem. Because i can't manage MethodCall.invokeSuper() in this case.
.intercept(MethodCall
.run(() -> System.out.println("Before"))
.andThen(MethodCall.invokeSuper())
.andThen(MethodCall
.run((() -> System.out.println("After")))))
Have a look at MethodDelegation, for example:
public class MyDelegation {
#RuntimeType
public static Object intercept(#SuperCall Callable<?> superCall) throws Exception {
// to do some work
Object o = superCall.call();
// to do some work
return o;
}
}
Then using:
.intercept(MethodDelegation.to(MyDelegation.class))
You can check the javadoc for MethodDelegation for more annotations that you can use to inject contextual information.

Intercept default method of the interface with returning value

I would like to intercept method after returning a value.
The method is the default method on the interface and I would like to have returning value of the default intf implementation and also overriding implementation in the concrete class.
this is my aspect:
#Aspect
#Configuration
public class ResAspect {
#AfterReturning(pointcut = "within(org.my.app.Strategy+) && execution(* shouldEnter(..))", returning = "res")
public void shouldOperate(JoinPoint jp, boolean res) {
System.out.println();
}
}
this is the default method:
default boolean shouldEnter(int i, Rec r) {
return !evaluate(i, r);
}
as you can guess it's not working. So can I achieve what I want with Spring AOP?
Can I access the implementing class instance and it's properties within the aspect?
EDIT: the interface I want to intercept is located in another module
You can access the instance on which the method is invoked, aka the target, inside the advice as follows:
YourInterface interfaceReference = (YourInterface) joinPoint.getTarget();
You can then access whatever you want using the retrieved object.

Where is the right place for annotation processing?

I write simple application. I don't want to use any frameworks. Please suggest me right place to hold annotation processing.
I have a few lines in main method:
String myString = (#NonNull String)list;
And I created #interface:
#Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public #interface NonNull {
}
Which step should I take next? Can I work with annotations without using reflection? Could you expose for me samples of such annotation processing code?
There is no way (AFAIK) to work with annotations without reflection.
If you don't want to use any framework, first step is to write kind of proxy class handling the method requests. It is an example of method processing with annotation use over method:
public class MyProxy {
private <T> T getProxy(T t) {
return (T) Proxy.newProxyInstance(t.getClass().getClassLoader(), new Class<?>[]{MyClass.class}, new MyInvocationHandler(t));
}
}
And then implement InvocationHandler:
public class MyInvocationHandler implements InvocationHandler {
private Object obj;
MyInvocationHandler (Object obj) {
this.obj = obj;
}
#Override
public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
boolean isNotNull = method.isAnnotationPresent(NotNull.class);
if (isNotNull) {
/* process annotated method. Or go through proxy object fields etc.. */
}
}
}
I hope it will help you.
You didn't say what kind of annotation processing you want to do.
Do you want to add a run-time check that will cause your code to crash if list is ever null at run time? For this, reflection will work.
Do you want to add a compile-time check that will reject your code if it cannot prove that list is never null at run time? For this, an annotation processor such as the Checker Framework will work.
Your question does not explain why you don't want to use a framework. Doing so will save you from re-implementing a lot of functionality that others have already created.

AspectJ exchange data between Advice and JoinPoint

I am looking for a way to pass objects between Advice and JoinPoint, something like the following,
#Aspect
class SomeAspect {
#Around(execution * *.*(..) && #annotation(sample))
public Object PassbyRef(PJP pjp) {
SomeObjectToPass someObj = new SomeObjecttoPass();
Object retVal = pjp.proceed(someObj);
//process(someObj);
}
}
class UsingAspect {
#sample
public Object TestMethod() {
//how do I access someObj in this method?
}
}
I am looking to perform some action before execution of a method/JP, then I need to way to communicate between advice and method being executed, then I need to perform more actions after method has been executed.
Strange idea but if your design requires this You can try something like that:
just add a getter to your Advice class or maybe create an interface that requires this
class UsingAspect {
public getSomeObj(){return someObj};
}
and then from Aspect
if (joinPoint.getTarget().getClass() == UsingAspect.class){
UsingAspect ua=(UsingAspect)joinpoint.getTarget();
ua.getSomeObj()
}
Then in Advice and Aspect you should have reference to the same someObj. If you would like to do this in reverse direction just add a setter and save an object to your Advice class.

Code injection via custom annotation

Here's my use case:
I need to do some generic operation before and after each method of a given class, which is based on the parameter(s) of the method. For example:
void process(Processable object) {
LOGGER.log(object.getDesc());
object.process();
}
class BaseClass {
String method1(Object o){ //o may or may not be Processable(add process logic only in former case)
if(o intstanceof Prcessable){
LOGGER.log(object.getDesc());
object.process();
}
//method logic
}
}
My BaseClass has a lot of methods and I know for a fact that the same functionality will be added to several similar classes as well in future.
Is something like the following possible?
#MarkForProcessing
String method1(#Process Object o){
//method logic
}
PS: Can AspectJ/guice be used? Also want to know how to implement this from scratch for understanding.
Edit: Forgot to mention, what I have tried.(Not complete or working)
public #interface MarkForProcessing {
String getMetadata();
}
final public class Handler {
public boolean process(Object instance) throws Exception {
Class<?> clazz = instance.getClass();
for(Method m : clazz.getDeclaredMethods()) {
if(m.isAnnotationPresent(LocalSource.class)) {
LocalSource annotation = m.getAnnotation(MarkForProcessing.class);
Class<?> returnType = m.getReturnType();
Class<?>[] inputParamTypes = m.getParameterTypes();
Class<?> inputType = null;
// We are interested in just 1st param
if(inputParamTypes.length != 0) {
inputType = inputParamTypes[0];
}
// But all i have access to here is just the types, I need access to the method param.
}
return false;
}
return false;
}
Yes, it can be done. Yes, you can use AspectJ. No, Guice would only be tangentially related to this problem.
The traditional aspect approach creates a proxy which is basically a subclass of the class you've given it (e.g. a subclass of BaseClass) but that subclass is created at runtime. The subclass delegates to the wrapped class for all methods. However, when creating this new subclass you can specify some extra behavior to add before or after (or both) the call to the wrapped class. In other words, if you have:
public class Foo() {
public void doFoo() {...}
}
Then the dynamic proxy would be a subclass of Foo created at runtime that looks something like:
public class Foo$Proxy {
public void doFoo() {
//Custom pre-invocation code
super.doFoo();
//Custom post-invocation code
}
}
Actually creating a dynamic proxy is a magical process known as bytecode manipulation. If you want to to do that yourself you can use tools such as cglib or asm. Or you can use JDK dynamic proxies. The main downside to JDK proxies are that they can only wrap interfaces.
AOP tools like AspectJ provide an abstraction on top of the raw bytecode manipulation for doing the above (you can do a lot with bytecode manipulation, adding behavior before and after methods is all aspects allow). Typically they define 'Aspect's which are classes that have special methods called 'advice' along with a 'pointcut' which defines when to apply that advice. In other words you may have:
#Aspect
public class FooAspect {
#Around("#annotation(MarkForProcessing)")
public void doProcessing(final ProceedingJoinPoint joinPoint) throws Throwable
{
//Do some before processing
joinPoint.proceed(); //Invokes the underlying method
//Do some after processing
}
}
The aspect is FooAspect, the advice is doProcessing, and the pointcut is "#annotation(MarkForProcessing)" which matches all methods that are annotated with #MarkForProcessing. It's worth pointing out that the ProceedingJoinPoint will have a reference to the actual parameter values (unlike the java.lang.reflect.Method)
The last step is actually applying your aspect to an instance of your class. Typically this is either done with a container (e.g. Guice or Spring). Most containers have some way of knowing about a collection of aspects and when to apply them to classes constructed by that container. You can also do this programmatically. For example, with AspectJ you would do:
AspectJProxyFactory factory = new AspectJProxyFactory(baseClassInstance);
factory.addAspect(FooAspect.class);
BaseClass proxy = factory.getProxy();
Last, but not least, there are AOP implementations which use compile-time "weaving" which is a second compilation step run on the class files that applies the aspects. In other words, you don't have to do the above or use a container, the aspect will be injected into the class file itself.

Categories

Resources