I have the following generic cglib method interceptor implementation:
public class EntityInterceptor<T, PK> implements MethodInterceptor{
private EntityChangeType changeType;
private T entity;
private GenericCrudMapper<T,PK> mapper;
public EntityInterceptor(T entity, GenericCrudMapper<T, PK> mapper){
this.entity = entity;
this.mapper = mapper;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// pass through
return proxy.invoke(entity, args);
}
public void setEntityChangeType(EntityChangeType changeType){
this.changeType = changeType;
}
public void saveChanges(){
// @todo
}
}
Which is used as follows:
@Override
public Airport get(String id) {
Airport airport = airportMapper.findById(id);
if(airport != null){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Airport.class);
enhancer.setCallback(new EntityInterceptor<>(airport, airportMapper));
airport = (Airport) enhancer.create();
return airport;
}
return airport;
}
Can I safely assume that the method interceptor created above will be instantiated per enhanced class instance (in other words, when assigning method interceptors, they are not shared between all class instances)?
Yes, you can be sure about this. Your solution is however fairly inefficient as a new class is generated for every instance. Instead, you should create your proxy based on the interceptor type:
// Do once
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(realObject.getClass());
enhancer.setCallbackType(Airport.class);
Class classForProxy = enhancer.createClass();
// Do for each instance
Enhancer.registerCallbacks(classForProxy, new Callback[]{new EntityInterceptor<>(airport, airportMapper});
Object createdProxy = classForProxy.newInstance();
This way you can reuse a single class for all proxy instances.