@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class AutoFillInterceptor implements Interceptor {
private ConcurrentHashMap<Class, AuditingConfig> auditingConfigMap = new ConcurrentHashMap<>();
private CurrentUserExtractor currentUserExtractor;
public void setCurrentUserExtractor(CurrentUserExtractor currentUserExtractor) {
this.currentUserExtractor = currentUserExtractor;
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
Class<?> clazz = arg.getClass();
AuditingConfig config = auditingConfigMap.computeIfAbsent(clazz, this::extractConfig);
Field createField = config.getCreateField();
Field modifiedField = config.getModifiedField();
BeanWrapper beanWrapper = null;
MappedStatement mappedStatement = (MappedStatement)args[0];
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
if (createField != null || modifiedField != null) {
beanWrapper = new BeanWrapperImpl(arg);
if (sqlCommandType == SqlCommandType.INSERT) {
if (createField != null) {
setAuditingDateValue(beanWrapper, createField, now);
if (modifiedField != null) {
setAuditingDateValue(beanWrapper, modifiedField, now);
// if (config.getVersionFiled() != null) {
// setDefaultVersion(beanWrapper, config.getVersionFiled());
} else if (sqlCommandType == SqlCommandType.UPDATE) {
setAuditingDateValue(beanWrapper, modifiedField, now);
if (currentUserExtractor != null) {
Field createdByField = config.getCreatedByField();
Field modifiedByField = config.getModifiedByField();
if (createdByField != null && modifiedByField != null) {
Object user = currentUserExtractor.getCurrentUser();
if (beanWrapper == null) {
beanWrapper = new BeanWrapperImpl(arg);
if (sqlCommandType == SqlCommandType.INSERT) {
if (createField != null) {
setAuditingUserValue(beanWrapper, createdByField, user);
if (modifiedField != null) {
setAuditingUserValue(beanWrapper, modifiedByField, user);
} else if (sqlCommandType == SqlCommandType.UPDATE) {
setAuditingUserValue(beanWrapper, modifiedByField, user);
return invocation.proceed();
private void setAuditingDateValue(BeanWrapper beanWrapper, Field field, Date value) {
String name = field.getName();
if (field.getType() == Date.class) {
beanWrapper.setPropertyValue(name, value);
private void setAuditingUserValue(BeanWrapper beanWrapper, Field field, Object user) {
String name = field.getName();
if (beanWrapper.getPropertyValue(name) == null) {
beanWrapper.setPropertyValue(name, user);
private AuditingConfig extractConfig(Class<?> clazz) {
AuditingConfig config = new AuditingConfig();
ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
Created created = field.getAnnotation(Created.class);
config.setCreateField(field);
Modified modified = field.getAnnotation(Modified.class);
config.setModifiedField(field);
CreatedBy createdBy = field.getAnnotation(CreatedBy.class);
config.setCreatedByField(field);
ModifiedBy modifiedBy = field.getAnnotation(ModifiedBy.class);
if (modifiedBy != null) {
config.setModifiedByField(field);
// Version version = field.getAnnotation(Version.class);
// if (version != null) {
// config.setVersionFiled(field);
public Object plugin(Object target) {
return Plugin.wrap(target, this);
public void setProperties(Properties properties) {
private static class AuditingConfig {
private Field createField;
private Field modifiedField;
private Field createdByField;
private Field modifiedByField;
private Field versionFiled;