1
votes

I am working on one component to achieve audit using Spring AOP. I could use it for most of the service's methods. But found that with Mybatis mappers AOP point-cuts don't work.

Basically, Spring AOP only works with Spring-managed beans. But these mapper beans have been scanned using mybatis.spring.*.MapperScan and can be autowired in other Spring components.

Why can these beans not be scanned for Spring AOP? Any idea?

I can use AspectJ but was keen to find out how mybatis.spring.*.MapperScan works.

for example -

I have these configurations one for Mybatis mapper scan and other config for application specific configurations.

@Configuration
@MapperScan("com.test.mapper")
public class ProviderConfiguration {

   @Bean
   public SqlSessionFactory sqlSessionFactory(final DataSource src) throws Exception {
      ...
   }
}

@Configuration
@EnableAspectJAutoProxy
public class MainConfiguration {

}

My Dao logic where i call mapper method -

@Component
public class TestDao {

   //injecting mybatis mapper here
   @Inject
   private SaveTableData saveTableData;

   public TableData save(TableData tableData) {
       saveTableData.updateTableData(tableData);
   }
}

I have registered my pointcuts as below

@Component
@Aspect
public class TestAdvices {
  @Pointcut("execution(* com.test.mapper.SaveTableData.updateTableData(*))") 
  public void commonSaveTableData(TableData tableData) {
  }

  @Pointcut("execution(* com.test.service.CreateTableData.createTableData(*))") 
  public void commonCreateTableData(TableData tableData) {
  }  

  //advices
  @After("commonSaveTableData(tableData)")
  public void addHistoryWhenSaveTableData(TableData tableData) throws Throwable {
      //do stuff    
  }

  //advices
  @After("commonCreateTableData(tableData)")
  public void addHistoryWhenCreateTableData(TableData tableData) throws Throwable {
      //do stuff    
  }
}

Issue is commonCreateTableData which is on service method works as expected. But commonSaveTableData which is on Mybatis mapper method does't get invoke.

Question is if i can autowire these Mappers in any Spring bean why can't Spring AOP intercept method call using these pointcuts?

2
I have updated the question with the example. - Amit Naik
Can you add the Service Code - or wherever you make the call to the mapper? - Reg
its fairly simple call from my Dao class. i have updated it. - Amit Naik
Everything in the configuration looks good so far. Can you also show advices associated with the defined pointcuts? - Roman Konoval
Have added sample implementation for advices but it does not even get invoke with mapper mathods - Amit Naik

2 Answers

0
votes

I think your pointcut expression is not correct, try this

@Component
@Aspect
public class TestAdvices {
  @Pointcut("execution(* com.test.mapper.SaveTableData.updateTableData(*)) && args(tableData)", argNames="tableData") 
  public void commonSaveTableData(TableData tableData) {
  }



//advices
  @After("commonSaveTableData(tableData)", argNames="tableData")
  public void addHistoryWhenSaveTableData(TableData tableData) throws Throwable {
      //do stuff    
  }
//...
}
0
votes

The reason you can't cut into the mapper like this is that when mapper is scanned by mybatis, it's bean definition has bean changed in a way that its interface is still the mapper interface but its class has been changed to MapperFactoryBean