最近在学习Spring AOP,相较于AspectJ,Spring AOP是一种基于proxy的动态(run-time)AOP技术。它并不追求对AOP的完全支持,而是要求符合Spring的编程习惯,以Spring的风格编写AOP程序。
下面是一个实例:
定义业务逻辑层Service的接口
package com.simon.service;
public interface AccountService {
public void save(String loginname, String password);
}
Service的一个实现
package com.simon.service;
import com.simon.dao.AccountDao;
public class AccountServiceImpl implements AccountService{
private AccountDao dao;
public AccountServiceImpl(AccountDao dao) {
// TODO Auto-generated constructor stub
this.dao = dao;
}
@Override
public void save(String loginname, String password) {
// TODO Auto-generated method stub
dao.save(loginname, password);
}
}
Dao层实现:
package com.simon.dao;
public class AccountDao {
public void save(String loginname, String password){
System.out.println("store account info into db");
}
}
接下来定义日志切面,用于统一处理Service中的日志
package com.simon.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class LogAspect {
public void before(JoinPoint call){
String classname = call.getTarget().getClass().getName();
String methodname = call.getSignature().getName();
System.out.println(classname+" 类的 "+methodname+" 方法将被调用");
}
public void afterReturn() {
System.out.println("后置通知:方法正常结束了");
}
public void after(){
System.out.println("最终通知:不管方法有没有正常执行完成,一定会返回的");
}
public void afterThrowing() {
System.out.println("异常抛出后通知:方法执行时出异常了");
}
//用来做环绕通知的方法可以第一个参数定义为org.aspectj.lang.ProceedingJoinPoint类型
public Object doAround(ProceedingJoinPoint call) throws Throwable {
Object result = null;
this.before(call);//相当于前置通知
try {
result = call.proceed();
this.afterReturn(); //相当于后置通知
} catch (Throwable e) {
this.afterThrowing(); //相当于异常抛出后通知
throw e;
}finally{
this.after(); //相当于最终通知
}
return result;
}
}
LogAspect中定义了before, after, around等方法,对应Advice中的各个方法。
需要的类定义完后,有XML和注解两种方式配置Spring AOP,下面主要介绍XML方式。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="dao" class="com.simon.dao.AccountDao" />
<bean id="accountService" class="com.simon.service.AccountServiceImpl">
<constructor-arg ref="dao"/>
</bean>
<bean id="logAspectBean" class="com.simon.aspect.LogAspect"/>
<aop:config>
<aop:aspect id="logAspect" ref="logAspectBean">
<aop:pointcut id="allMethod" expression="execution(* com.simon.service.*.*(..))" />
<aop:before method="before" pointcut-ref="allMethod"/>
<aop:after-returning method="afterReturn" pointcut-ref="allMethod"/>
<aop:after method="after" pointcut-ref="allMethod"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="allMethod"/>
</aop:aspect>
</aop:config>
</beans>
定义测试类:
package com.simon.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.simon.service.AccountService;
public class Test {
public static void main(String[] args) {
ApplicationContext beanFactory = new FileSystemXmlApplicationContext("applicationContext.xml");
AccountService service = (AccountService) beanFactory.getBean("accountService");
service.save("simon", "109445");
}
}
运行Spring AOP除了需要Spring的一系列jar包之外,还需要
aspectjrt.jar:提供JoinPoint, ProceedingJoinPoint等的实现
aopalliance.jar