-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for AOP Alliance method interceptors
- Loading branch information
Showing
7 changed files
with
357 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,8 @@ gradle-app.setting | |
!gradle-wrapper.jar | ||
|
||
# IntelliJ IDEA | ||
.idea/ | ||
classes/ | ||
*.iml | ||
*.ipr | ||
*.iws | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
src/main/java/com/github/therapi/core/interceptor/MethodDefinitionInvocation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.github.therapi.core.interceptor; | ||
|
||
import com.github.therapi.core.MethodDefinition; | ||
import org.aopalliance.intercept.MethodInvocation; | ||
|
||
/** | ||
* A specialized method invocation that provides access to | ||
* the MethodDefinition of the method being invoked. | ||
*/ | ||
public interface MethodDefinitionInvocation extends MethodInvocation { | ||
MethodDefinition getMethodDefinition(); | ||
|
||
/** | ||
* Returns the fully qualified name of the remotable method being invoked. | ||
* Intended for use by MethodInterceptors that want to know the name of the method being intercepted. | ||
* | ||
* @throws ClassCastException if the given invocation does not implement {@code MethodDefinitionInvocation}. | ||
*/ | ||
static String getQualifiedName(MethodInvocation invocation) { | ||
return ((MethodDefinitionInvocation) invocation).getMethodDefinition().getQualifiedName("."); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
src/main/java/com/github/therapi/core/interceptor/MethodPredicates.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.github.therapi.core.interceptor; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.util.function.Predicate; | ||
|
||
import com.github.therapi.core.MethodDefinition; | ||
import org.aopalliance.intercept.MethodInterceptor; | ||
|
||
/** | ||
* Factory methods for common method predicates, useful for registering method interceptors. | ||
* | ||
* @see com.github.therapi.core.MethodRegistry#intercept(Predicate, MethodInterceptor) | ||
*/ | ||
public class MethodPredicates { | ||
private MethodPredicates() { | ||
} | ||
|
||
public static Predicate<MethodDefinition> any() { | ||
return methodDef -> true; | ||
} | ||
|
||
public static Predicate<MethodDefinition> methodAnnotatedWith(Class<? extends Annotation> annotationClass) { | ||
return methodDef -> methodDef.getMethod().getAnnotation(annotationClass) != null; | ||
} | ||
|
||
public static Predicate<MethodDefinition> qualifiedName(String name) { | ||
return methodDef -> methodDef.getQualifiedName(".").equals(name); | ||
} | ||
|
||
public static Predicate<MethodDefinition> namespace(String namespace) { | ||
return methodDef -> methodDef.getNamespace().orElse("").equals(namespace); | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
src/main/java/com/github/therapi/core/interceptor/SimpleMethodInvocation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package com.github.therapi.core.interceptor; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
import java.lang.reflect.AccessibleObject; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.util.List; | ||
|
||
import com.github.therapi.core.MethodDefinition; | ||
import com.google.common.collect.ImmutableList; | ||
import org.aopalliance.intercept.MethodInterceptor; | ||
|
||
/** | ||
* No-frills implementation of the AOP Alliance MethodInvocation interface. | ||
* Supports only static matching. If dynamic argument matching or other advanced | ||
* features are required, consider subclassing Spring's ReflectiveMethodInvocation | ||
* class instead. | ||
*/ | ||
public class SimpleMethodInvocation implements MethodDefinitionInvocation { | ||
private final MethodDefinition methodDefinition; | ||
private final Object[] arguments; | ||
private final ImmutableList<MethodInterceptor> interceptors; | ||
private int currentInterceptorIndex = -1; | ||
|
||
public SimpleMethodInvocation(MethodDefinition methodDefinition, Object[] args, List<MethodInterceptor> interceptors) { | ||
this.methodDefinition = requireNonNull(methodDefinition); | ||
this.arguments = requireNonNull(args); | ||
this.interceptors = ImmutableList.copyOf(interceptors); | ||
} | ||
|
||
@Override | ||
public MethodDefinition getMethodDefinition() { | ||
return methodDefinition; | ||
} | ||
|
||
@Override | ||
public Method getMethod() { | ||
return methodDefinition.getMethod(); | ||
} | ||
|
||
@Override | ||
public Object[] getArguments() { | ||
return arguments; | ||
} | ||
|
||
@Override | ||
public Object proceed() throws Throwable { | ||
return currentInterceptorIndex == interceptors.size() - 1 | ||
? invokeTargetMethod() | ||
: interceptors.get(++currentInterceptorIndex).invoke(this); | ||
} | ||
|
||
protected Object invokeTargetMethod() throws Throwable { | ||
Method method = methodDefinition.getMethod(); | ||
|
||
try { | ||
return method.invoke(methodDefinition.getOwner(), arguments); | ||
|
||
} catch (IllegalAccessException e) { | ||
method.setAccessible(true); | ||
return method.invoke(methodDefinition.getOwner(), arguments); | ||
|
||
} catch (InvocationTargetException e) { | ||
throw e.getTargetException(); | ||
} | ||
} | ||
|
||
@Override | ||
public Object getThis() { | ||
return methodDefinition.getOwner(); | ||
} | ||
|
||
@Override | ||
public AccessibleObject getStaticPart() { | ||
return methodDefinition.getMethod(); | ||
} | ||
} |
Oops, something went wrong.