Reputation: 21134
I'm trying to come up with the best strategy to merge two classes in one using the ASM Core framework (not the Tree one).
As the ClassReader and ClassVisitor are strictly bound to a single class, how would you do that?
I already searched in the official Docs, but everything is implemented using a ClassNode, which is from the Tree module.
Say we have a base generic interface:
public interface CrudDao<T, ID>
{
T select(final ID id);
boolean update(final T object);
boolean insert(final T object);
boolean delete(final ID id);
}
And a concrete generic implementation:
public class MyCrudDao<T, ID> implements CrudDao<T, ID>
{
@Override
public T select(final ID id) {
...
}
@Override
public boolean update(final T object) {
...
}
@Override
public boolean insert(final T object) {
...
}
@Override
public boolean delete(final ID id) {
...
}
}
Now we define an abstract class which extends CrudDao
, providing additional functionalities or overriding the interface methods, while remaining indifferent to the concrete implementation:
public abstract class ConfigurationDao implements CrudDao<Configuration, String>
{
public List<Configuration> selectAll() {
...
}
@Override
public int count() {
...
}
}
What I'd like to obtain with ASM is a new concrete class which extends ConfigurationDao
, which proxy the methods of the CrudDao
interface to the MyCrudDao
implementation (if not already overridden, see count()
above) and which simply copy the abstract class methods.
I actually implemented this after Rafael answer, but after a simple benchmark it seems slow compared to what is reported on the ByteBuddy website.
I got around 25-30 ms from the accept()
call to the toByteArray()
call (excluded)
Upvotes: 1
Views: 260
Reputation: 44032
If you only want to copy unrelated members of two simple classes such as DTOs into the same target class, you can do this by creating one ClassWriter
and visit both classes that you want to merge:
ClassWriter cw = ...
cw.visit(...);
ClassReader cr1 = new ClassReader("foo.Bar"), cr2 = new ClassReader("qux.Baz");
cr1.accept(new MergeGuard(cw), 0);
cr2.accept(new MergeGuard(cw), 0);
cw.visitEnd();
In order to avoid that you writer the class file header twice, you have to override the relevant methods in MergeGuard
that needs to extend ClassVisitor
to be empty rather then to delegate to the super method which would invoke those methods on your ClassWriter
.
Upvotes: 1