Spring中可以使用注解或XML文件配置的方式实现AOP。
1、导入jar包
- com.springsource.net.sf.cglib -2.2.0.jar
- com.springsource.org.aopalliance-1.0.0 .jar
- com.springsource.org.aspectj.weaver-1.6.8 .RELEASE.jar
- commons-logging-1.1.3. jar
- spring-aop-4.0.0.RELEASE.jar
- spring-aspects-4.0.0.RELEASE.jar
- spring-beans-4.0.0.RELEASE.jar
- spring-context-4.0.0.RELEASE.jar
- spring-core-4.0.0.RELEASE.jar
- spring-expression-4.0.0.RELEASE.jar
aspectaop相关jar包 ---> 资源目录--->jar包资源--->AOP日志打印相关jar包(切面类)
Spring相关jar包 ---> 资源目录--->jar包资源--->Spring相关jar包
2、新建代理类和切面类
1 @Component 2 public class MathCalculator { 3 public void add(int i, int j) { 4 int result=i+j; 5 System.out.println("目标方法add(int)执行了"); 6 } 7 public void sub(int i, int j) { 8 int result=i-j; 9 System.out.println("目标方法sub执行了"); 10 } 11 public void mult(int i, int j) { 12 int result=i*j; 13 System.out.println("目标方法mult执行了"); 14 } 15 public void div(int i, int j) { 16 int result=i/j; 17 System.out.println("目标方法div执行了"); 18 } 19 }
切面类1:LogAspectp1:声明4中通知方法,Before、After、AfterThrowing、AfterReturning
1 public class LogAspectp1{ 2 public void showBeginLog(JoinPoint jPoint){ 3 Object[] args = jPoint.getArgs();//获取方法参数 4 List<Object> asList = Arrays.asList(args);//转化成List集合 5 Signature signature = jPoint.getSignature(); 6 String name = signature.getName();//获取方法的名字 7 System.out.println("LogAspectp1-----AOP日志开始"); 8 System.out.println("目标方法名:"+name+",参数列表:"+asList); 9 } 10 public void showAfterLog(){ 11 System.out.println("LogAspectp1-----AOP方法结束"); 12 } 13 public void showExceptionLog(Exception ex){ 14 System.out.println("LogAspectp1-----AOP方法异常"); 15 System.out.println("异常信息:"+ex.getMessage()); 16 } 17 public void showReturnLog(Object result){ 18 System.out.println("方法返回值:"+result); 19 System.out.println("LogAspectp1-----AOP方法最终返回"); 20 } 21 }
切面类2:LogAspectp2:声明Around通知方法,代替前面的4中通知
1 public class LogAspectp2{ 2 public Object showLog(ProceedingJoinPoint point){ 3 Object[] args = point.getArgs(); 4 List<Object> asList = Arrays.asList(args); 5 Signature signature = point.getSignature(); 6 String name = signature.getName(); 7 Object result = null; 8 try { 9 try { 10 //目标方法之前要执行的操作,相当于@before 11 System.out.println("LogAspect2-----[环绕日志]"+name+"开始了,参数为:"+asList); 12 //调用目标方法 13 result = point.proceed(args); 14 } finally { 15 //方法最终结束时执行的操作,相当于@after 16 System.out.println("LogAspect2-----[环绕日志]"+name+"结束了!"); 17 } 18 //目标方法正常执行之后的操作,相当于@AfterReturning 19 System.out.println("LogAspect2-----[环绕日志]"+name+"返回了,返回值为:"+result); 20 } catch (Throwable e) { 21 //目标方法抛出异常信息之后的操作,相当于@AfterThrowing 22 System.out.println("LogAspect2-----[环绕日志]"+name+"出异常了,异常对象为:"+e); 23 throw new RuntimeException(e.getMessage()); 24 } 25 return result; 26 } 27 }
3、在Spring的配置文件applicationContext.xml中进行配置
1 <!-- 将需要加载到IOC容器中的bean配置好 --> 2 <bean id="mathCalculator" class="com.bwlu.common.MathCalculator"></bean> 3 <bean id="logAspectp1" class="com.bwlu.common.LogAspectp1"></bean> 4 <bean id="logAspectp2" class="com.bwlu.common.LogAspectp2"></bean> 5 <!-- 配置AOP,需要导入AOP名称空间 --> 6 <aop:config> 7 <!-- 声明切入点表达式 --> 8 <aop:pointcut expression="execution(public * com.bwlu.aop.MathCalculatorImpl.*(..))" id="pointcut"/> 9 <!-- 配置日志切面类,引用前面的类 ,通过order属性控制优先级--> 10 <aop:aspect ref="logAspectp1" order="20"> 11 <!-- 通过method属性指定切面类的切面方法,通过pointcut-ref指定切入点表达式 --> 12 <aop:before method="showBeginLog" pointcut-ref="pointcut"/> 13 <aop:after method="showAfterLog" pointcut-ref="pointcut"/> 14 <aop:after-throwing method="showExceptionLog" pointcut-ref="pointcut" throwing="ex"/> 15 <aop:after-returning method="showReturnLog" pointcut-ref="pointcut" returning="result"/> 16 </aop:aspect> 17 <aop:aspect ref="logAspectp2" order="10"> 18 <aop:around method="showLog" pointcut-ref="pointcut"/> 19 </aop:aspect> 20 </aop:config>
4、新建Junit测试类进行测试
1 ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml"); 2 @Test 3 public void test() { 4 //需要进行强转,如果该类实现了一个接口(并且切入点表达式指向这个类),那么获取到的将不是该类的对象,需要强转 5 //MathCalculatorImpl实现了MathCalculator接口,则 6 //MathCalculator bean = (MathCalculator)ioc.getBean("mathCalculatorImpl"); 7 MathCalculator bean = (MathCalculator)ioc.getBean("mathCalculator"); 8 bean.add(10, 5); 9 System.out.println(); 10 bean.add(10.0, 5); 11 System.out.println(); 12 bean.sub(10, 5); 13 System.out.println(); 14 bean.mult(10, 5); 15 System.out.println(); 16 bean.div(10, 0); 17 }
运行结果:
1 LogAspectp2-----[环绕日志]add开始了,参数为:[10, 5] 2 LogAspectp1-----AOP日志开始 3 目标方法名:add,参数列表:[10, 5] 4 目标方法add(int)执行了 5 LogAspectp1-----AOP方法结束 6 方法返回值:null 7 LogAspectp1-----AOP方法最终返回 8 LogAspectp2-----[环绕日志]add结束了! 9 LogAspectp2-----[环绕日志]add返回了,返回值为:null 10 11 LogAspectp2-----[环绕日志]add开始了,参数为:[10.0, 5.0] 12 LogAspectp1-----AOP日志开始 13 目标方法名:add,参数列表:[10.0, 5.0] 14 目标方法add(double)执行了 15 LogAspectp1-----AOP方法结束 16 方法返回值:15.0 17 LogAspectp1-----AOP方法最终返回 18 LogAspectp2-----[环绕日志]add结束了! 19 LogAspectp2-----[环绕日志]add返回了,返回值为:15.0 20 21 LogAspectp2-----[环绕日志]sub开始了,参数为:[10, 5] 22 LogAspectp1-----AOP日志开始 23 目标方法名:sub,参数列表:[10, 5] 24 目标方法sub执行了 25 LogAspectp1-----AOP方法结束 26 方法返回值:null 27 LogAspectp1-----AOP方法最终返回 28 LogAspectp2-----[环绕日志]sub结束了! 29 LogAspectp2-----[环绕日志]sub返回了,返回值为:null 30 31 LogAspectp2-----[环绕日志]mult开始了,参数为:[10, 5] 32 LogAspectp1-----AOP日志开始 33 目标方法名:mult,参数列表:[10, 5] 34 目标方法mult执行了 35 LogAspectp1-----AOP方法结束 36 方法返回值:null 37 LogAspectp1-----AOP方法最终返回 38 LogAspectp2-----[环绕日志]mult结束了! 39 LogAspectp2-----[环绕日志]mult返回了,返回值为:null 40 41 LogAspectp2-----[环绕日志]div开始了,参数为:[10, 0] 42 LogAspectp1-----AOP日志开始 43 目标方法名:div,参数列表:[10, 0] 44 LogAspectp1-----AOP方法结束 45 LogAspectp1-----AOP方法异常 46 异常信息:/ by zero 47 LogAspectp2-----[环绕日志]div结束了! 48 LogAspectp2-----[环绕日志]div出异常了,异常对象为:java.lang.ArithmeticException: / by zero