AOP:面向切面编程,又叫面向方面编程。是面向对象的一个补充。
aop解决的问题:把分散在程序中每一个角落的重复代码提取到一个类(方面)中,在执行功能的时候,自动先执行方面中的代码。
aop的应用:事务的管理,操作日志的记录,异常的记录。
代码:
目录结构:
配置文件:
<!-- 自动扫描com.edu包下的注解 -->
<context:component-scan base-package="com.edu"></context:component-scan>
<!-- 自动创建代理 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
接口中的代码:
package com.edu.arit;
public interface Arithmetic {
public int add(int i,int j);
public int sub(int i,int j,int k);
public int div(int i,int j);
public int mul(int i,int j);
}
实现类中的代码:
package com.edu.arit.impl;
import org.springframework.stereotype.Component;
import com.edu.arit.Arithmetic;
@Component("arithmetic")
public class ArithmeticImpl implements Arithmetic {
@Override
public int add(int i, int j) {
return i+j;
}
@Override
public int sub(int i, int j, int k) {
return i-j-k;
}
@Override
public int mul(int i, int j) {
return i*j;
}
@Override
public int div(int i, int j) {
return i/j;
}
}
切面类中的代码:
package com.edu.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect //表明该类是一个切面
@Component
public class ArithmeticAop {
//在执行com.edu.arit.impl.*.*(..))下面的方法之前加上下面方法的内容
@Before(value="execution(* com.edu.arit.impl.*.*(..))")
public void before(JoinPoint jp){
System.out.println("before方法执行");
}
//还可以写其他方法
}
@Before(value="execution(* com.edu.arit.impl.*.*(..))")中三个*表示的意义:
第一个* :方法的返回值
第二个* :com.edu.arit.impl包下的所有类
第三个* :该类中的所有方法
两个点表示的含义:任意参数
当然,也可以不用*和..,可以写具体的类,具体的方法,具体的参数,具体返回值。
测试代码:
package aop;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.edu.arit.Arithmetic;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:beans.xml"})
public class Aoptest extends AbstractJUnit4SpringContextTests{
@Resource(name="arithmetic")
private Arithmetic arithmetic;
@Test
public void testAdd() {
int i=arithmetic.add(10, 20);
System.out.println(i);
}
@Test
public void testSub() {
int i = arithmetic.div(10, 20);
System.out.println(i);
}
@Test
public void testDiv() {
int i = arithmetic.mul(10, 20);
System.out.println(i);
}
@Test
public void testMul() {
int i = arithmetic.sub(10, 20, 10);
System.out.println(i);
}
}
测试结果:
注意:aop依赖于spring的IoC,不能单独使用。
aop中的5个常用注解:
1.@Before 前置通知,调用方法之前执行该功能。该方法的返回值是void,参数是JoinPoint类型的。
2.@After 后置通知。该方法的返回值是void,参数是JoinPoint类型的。
3.@Afterrturning 方法返回值通知。该方法的返回值是void,参数有2个,一个是JoinPoint类型的,另一个是Object。
4.@Afterthrowing 异常通知,发生异常时执行该功能。该方法的返回值是void,参数有2个,一个是JoinPoint类型的,另一个是Execption。
5.@Round 环绕通知,相当于以上4个的综合。该方法的返回值是Object,参数的返回值是ProceedingJoinPoint类型。
该方法用注解是可以用proceedingJoinPoint.proceed()得到原方法的返回值,可以对其进行修改。慎用。