Creates dynamic proxies of concrete classes.
This is similar to the java.lang.reflect.Proxy class, but works for classes instead of
interfaces.
Example
The following example demonstrates the creation of a dynamic proxy for
java.util.Random
which will always return 4 when asked for integers, and which logs method calls to every method.
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("nextInt")) {
// Chosen by fair dice roll, guaranteed to be random.
return 4;
}
Object result = ProxyBuilder.callSuper(proxy, method, args);
System.out.println("Method: " + method.getName() + " args: "
+ Arrays.toString(args) + " result: " + result);
return result;
}
};
Random debugRandom = ProxyBuilder.forClass(Random.class)
.dexCache(getInstrumentation().getTargetContext().getDir("dx", Context.MODE_PRIVATE))
.handler(handler)
.build();
assertEquals(4, debugRandom.nextInt());
debugRandom.setSeed(0);
assertTrue(debugRandom.nextBoolean());
Usage
Call
forClass(Class) for the Class you wish to proxy. Call
handler(InvocationHandler) passing in an
InvocationHandler, and then call
build(). The returned instance will be a dynamically generated subclass where all method
calls will be delegated to the invocation handler, except as noted below.
The static method callSuper(Object, Method, Object...) allows you to access the original
super method for a given proxy. This allows the invocation handler to selectively override some
methods but not others.
By default, the build() method will call the no-arg constructor belonging to the class
being proxied. If you wish to call a different constructor, you must provide arguments for both
constructorArgTypes(Class[]) and constructorArgValues(Object[]).
This process works only for classes with public and protected level of visibility.
You may proxy abstract classes. You may not proxy final classes.
Only non-private, non-final, non-static methods will be dispatched to the invocation handler.
Private, static or final methods will always call through to the superclass as normal.
The finalize() method on Object will not be proxied.
You must provide a dex cache directory via the dexCache(File) method. You should take
care not to make this a world-writable directory, so that third parties cannot inject code into
your application. A suitable parameter for these output directories would be something like
this:
getApplicationContext().getDir("dx", Context.MODE_PRIVATE);
If the base class to be proxied leaks the this pointer in the constructor (bad practice),
that is to say calls a non-private non-final method from the constructor, the invocation handler
will not be invoked. As a simple concrete example, when proxying Random we discover that it
internally calls setSeed during the constructor. The proxy will not intercept this call during
proxy construction, but will intercept as normal afterwards. This behaviour may be subject to
change in future releases.
This class is not thread safe.
org.droidparts.dexmaker.stock
back to summary
private Class ProxyBuilder.MethodSetEntry
extends Object
- Class Inheritance
-
Wrapper class to let us disambiguate
Method objects.
The purpose of this class is to override the equals(Object) and hashCode()
methods so we can use a Set to remove duplicate methods that are overrides of one
another. For these purposes, we consider two methods to be equal if they have the same
name, return type, and parameter types.
Field Summary
| Modifier and Type | Field and Description
|
|---|
| private final String |
|
| private final Method |
|
| private final Class<?>[] |
|
| private final Class<?> |
|
Constructor Summary
| Access | Constructor and Description
|
|---|
| public |
|
Method Summary
| Modifier and Type | Method and Description
|
|---|
| public boolean |
|
| public int |
|
- Inherited from java.lang.Object:
-
clonefinalizegetClassnotifynotifyAlltoStringwaitwaitwait
Field Detail
| name | back to summary
|
|---|
| private final String name
|
| originalMethod | back to summary
|
|---|
| private final Method originalMethod
|
| paramTypes | back to summary
|
|---|
| private final Class<?>[] paramTypes
|
| returnType | back to summary
|
|---|
| private final Class<?> returnType
|
Constructor Detail
| MethodSetEntry | back to summary
|
|---|
| public MethodSetEntry(Method method)
|
Method Detail
| equals | back to summary
|
|---|
| public boolean equals(Object o) Overrides java.lang.Object.equals.
Doc from java.lang.Object.equals.
Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation
on non-null object references:
- It is reflexive: for any non-null reference value
x, x.equals(x) should return
true.
- It is symmetric: for any non-null reference values
x and y, x.equals(y)
should return true if and only if
y.equals(x) returns true.
- It is transitive: for any non-null reference values
x, y, and z, if
x.equals(y) returns true and
y.equals(z) returns true, then
x.equals(z) should return true.
- It is consistent: for any non-null reference values
x and y, multiple invocations of
x.equals(y) consistently return true
or consistently return false, provided no
information used in equals comparisons on the
objects is modified.
- For any non-null reference value
x,
x.equals(null) should return false.
An equivalence relation partitions the elements it operates on
into equivalence classes; all the members of an
equivalence class are equal to each other. Members of an
equivalence class are substitutable for each other, at least
for some purposes.
- Parameters
- o:Object
the reference object with which to compare.
- Returns:boolean
true if this object is the same as the obj
argument; false otherwise.
- Annotations
- @Override
|
| hashCode | back to summary
|
|---|
| public int hashCode() Overrides java.lang.Object.hashCode.
Doc from java.lang.Object.hashCode.
Returns a hash code value for this object. This method is
supported for the benefit of hash tables such as those provided by
java.util.HashMap.
The general contract of hashCode is:
- Whenever it is invoked on the same object more than once during
an execution of a Java application, the
hashCode method
must consistently return the same integer, provided no information
used in equals comparisons on the object is modified.
This integer need not remain consistent from one execution of an
application to another execution of the same application.
- If two objects are equal according to the
equals method, then calling the hashCode method on each of the two objects must produce the
same integer result.
- It is not required that if two objects are unequal
according to the
equals method, then
calling the hashCode method on each of the two objects
must produce distinct integer results. However, the programmer
should be aware that producing distinct integer results for
unequal objects may improve the performance of hash tables.
- Returns:int
a hash code value for this object
- Annotations
- @Override
|