0

I use spring and ibatis in my project, here is my question.

I want to trace all changes like add/update/delete and log them into table T_TRACE_LOG. The table has columns: operation_type, object_type, log_content, log_date.

Here is an example record:

"add", "customer", "name='andy',age=23,...", 2012-06-14 17:04:57.410

The log_content comes from Customer.toString(), I want this process automatically, so the AOP comes into my mind.

I can't control the client code, because some uses addCustomer() and some uses insertCustomer() and others use createCustomer(). But all of them called getSqlMapClientTemplate().insert("inserCustomer", Customer) at last. So I want to pointcut on getSqlMapClientTemplate().insert() to match them all.

Here is my trying, but it doesn't work:

 <aop:pointcut  expression="execution(* org.springframework.orm.ibatis.SqlMapClientTemplate.insert(..))" id="insertLogPointCut"/>

It works If I change the expression as below:

<aop:pointcut expression="execution(* com.xxx.CustomerDaoImpl.insert(..))" id="logPointCut"/>

Because AOP compiles the "pointcut information" into class bytecode based on source code, so I think it's impossible to pointcut on the ibatis class. If it's wrong, how to handle my situation?

Here is the configuration:

<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="traceLogger" class="com.xx.TraceLogger"/>
<aop:config>
    <aop:pointcut expression="execution(* com.xx.CustomerDaoImpl.insert(..))" id="insertLogPointCut"/>
    <aop:aspect id="logAspect" ref="traceLogger">
        <aop:after-returning method="logAfterReturning" pointcut-ref="insertLogPointCut"/>
    </aop:aspect>
</aop:config>
justin.xxt
  • 11
  • 2

1 Answers1

1

Default AOP behavior in Spring only works with interface (because it is using Java's dynamic proxy). It won't work if the pointcut is set on a concrete class.

SqlMapClientTemplate, if I remember correctly, is a class.

You have the choice of

  1. using cg-lib for proxy creation, or
  2. change your bean to use SqlMapClientOperations instead of SqlMapClientTemplate, and write have pointcut as "execution(* org.springframework.orm.ibatis.SqlMapClientOperations.insert(..))"

I shall recommend method 2.

And, your guess is wrong. AOP related stuff is not compiled into corresponding bytecode. They are all done in runtime (for the case in Spring)

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
  • Yes, you are right. Spring AOP is different with AspectJ. Spring AOP uses dynamic proxy pattern so it functions in runtime. AspectJ's ajc compiles into the bytecode. – justin.xxt Jun 14 '12 at 10:56
  • For your method2, I still don't know how. My `CustomerDaoImpl` extends from `SqlMapClientDaoSupport`, and I simply call `getSqlMapClientTemplate().insert("addCustomer", customer)` in my addCustomer(customer) method. Then how to use SqlMapClientOperations instead? – justin.xxt Jun 14 '12 at 11:09
  • Thanks for your information. It's my fault, I found the problem. I called `getSqlMapClientTemplate().insert("addCustomer", customer)` in the DaoImpl's method, which is not a part of the Dao Interface, it's just called by another interface method in a loop (insert many customers). I added the method to the Dao interface and it works. Thanks! – justin.xxt Jun 15 '12 at 01:37