I have a class which defines row access for a database.
public abstract class DBRow {
int index;
DBConnection connection;
public DBRow(DBConnection con, int id) {
connection = con;
index = id;
}
public DBRow(DBConnection con) {
this(con, -1);
}
public abstract String getTableName();
private static String getFieldName(Field field) {
...
}
public void save() {
... (Reads all fields that are annotated with @InDB and saves them
}
public void load() {
... (Will load a row from the database or create a new one if index == -1)
}
}
A specific row in the database extends this DBRow class. For example:
public class Test extends DBRow {
@InDB
public String vct;
@InDB
public int intt;
public Test(DBConnection con, int id) {
super(con, id);
vct = "test";
intt = 123;
}
@Override
public String getTableName() {
return "test";
}
}
After the constructor was called "load" should be called, so the row gets loaded from the database or will be created and saved properly.
public aspect DBRowLoadSave {
pointcut load() : execution(DBRow.new(*, *));
after() : load() {
((DBRow)thisJoinPoint.getThis()).load();
}
}
My problem is, that at this point the fields will not be initialized, because the pointcut listens to the constructor call in the mother class of Test, not in Test itself. Is there a way I can listen to all constructors of child classes, or is there another way I can execute the load method after the complete initilization of the class?
execution(DBRow+.new(..))
matches all subclass constructors, but includes the base class. So you need to exclude it via !execution(DBRow.new(..))
.
Furthermore you can bind the created object directly to a variable via this()
, avoiding the getThis()
call and the cast within the advice.
public aspect DBRowLoadSave {
pointcut load(DBRow dbRow) :
execution(DBRow+.new(..)) &&
!execution(DBRow.new(..)) &&
this(dbRow);
after(DBRow dbRow) : load(dbRow) {
System.out.println(thisJoinPoint);
dbRow.load();
}
}