AOP为应用程序开发者定义了一组高层次的概念,用于表达横切关注点。首先,在某个特定的执行点所执行的横切动作被称封装在通知(Advice)里。例如,可将日志和验证动作封装在一个或多个通知里。
经典的Spring AOP支持4种类型的通知,它们分别作用于执行点的不同时间。在正式的AOP定义里,存在多个类型的执行点,包括方法执行,构造器和字段访问。不过,Spring AOP只支持方法执行。所以,4种经典通知可以简化下面这样:
package intf;
public interface ICalc {
//加
public int add(int a,int b);
//减
public int sub(int a,int b);
//乘
public int mul(int a,int b);
//除
public int div(int a,int b);
}
package intf;
public class CalcImp implements ICalc {
public int add(int a, int b) {
return a+b;
}
public int div(int a, int b) {
if(b==0){
throw new IllegalArgumentException("除数不能为0");
}
return a/b;
}
public int mul(int a, int b) {
return a*b;
}
public int sub(int a, int b) {
return a-b;
}
}
1,前置通知
public class CalcBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println(method.getName()+"方法执行前");
}
}
2,返回通知
public class CalcAfterAdvice implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
System.out.println(method.getName()+"方法执行完毕,结果为:"+returnValue);
}
}
3,异常通知
异常通知必须实行ThrowsAdvice接口,这个接口没有声明任何方法,不过每个方法名称必须是afterThrowing。异常的类型由方法的参数类型指定。
接下来是配置AOP:<!-- 计算器Bean --> <bean id="calcimp" class="intf.CalcImp"></bean> <!-- 前置通知Bean --> <bean id="calcBeforeAdvice" class="advice.CalcBeforeAdvice"></bean> <!-- 返回通知Bean --> <bean id="calcAfterAdvice" class="advice.CalcAfterAdvice"></bean> <bean id="calcProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 代理的目标接口 --> <property name="proxyInterfaces"> <list> <value>intf.ICalc</value> </list> </property> <!-- 代理的目标类 --> <property name="target" ><ref local="calcimp"></ref></property> <!--拦截器的名字,也就是通知 --> <property name="interceptorNames"> <list> <value>calcBeforeAdvice</value> <value>calcAfterAdvice</value> </list> </property> </bean>
代理接口也可以不写,默认情况下,ProxyFactoryBean可以自动侦测并代理目标Bean所实现的所有接口。测试:
public static void main(String[] args) { ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); ICalc calc=(ICalc)ac.getBean("calcProxy"); calc.add(2, 3); calc.sub(1, 9); }
输出结果:add方法执行前
add方法执行完毕,结果为:5
sub方法执行前
sub方法执行完毕,结果为:-8