切点,切面,如何定义切点,前置、后置、放回、异常、环绕通知的XML版

源码获取github

1.项目结构(jar包跟上个一样)

2.核心业务代码

package com.hs.service;

/** * 对外提供的核心业务,完成了加法/减法/乘法运算 */
public interface ArithmeticService {
   int add(int x, int y);

   int sub(int x, int y);

   int mul(int x, int y);

   int div(int x, int y);
}
package com.hs.service.impl;

import com.hs.service.ArithmeticService;
import org.springframework.stereotype.Service;

/** * 核心代码 */
@Service
public class ArithmeticServiceImpl implements ArithmeticService {
   @Override
   public int add(int x, int y) {
      //核心代码
      int result = x + y;
      return result;
   }

   @Override
   public int sub(int x, int y) {
      int result = x - y;
      return result;
   }

   @Override
   public int mul(int x, int y) {
      int result = x * y;
      return result;
   }

   @Override
   public int div(int x, int y) {
      int result = x / y;
      return result;
   }
}

3.切面

package com.hs.service.aspect;

import org.aspectj.lang.JoinPoint;

import java.util.Arrays;

//@Component
//@Aspect //标记这是切面
public class Logger {

   public void test01() {
      System.out.println("测试出order属性的作用");
   }

   //1.前置通知
   public void test05(JoinPoint jp) {
      //获取get
      System.out.println("==前置通知==");
      System.out.println(Arrays.asList(jp.getArgs()));
      System.out.println(jp.getSignature().getName());
      System.out.println(jp.getTarget().getClass().getName());
      System.out.println("==前置通知==");
   }

   //2.后置通知
   public void test06(JoinPoint jp) {
      System.out.println("==后置增强==");
      System.out.println(Arrays.asList(jp.getArgs()));
      System.out.println(jp.getSignature().getName());
      System.out.println(jp.getTarget().getClass().getName());
      System.out.println("==后置增强==");

   }
   //3.返回通知
   public void test07(JoinPoint jp, int hs) {
      System.out.println("==返回通知==");
      System.out.println("程序正常运行,正确的运行结果为==>" + hs);
      System.out.println("==返回通知==");
   }
   //4.异常通知
   public void test08(JoinPoint jp, ArithmeticException hs) {
      System.out.println("==异常通知==");
      System.out.println("程序运行错误==>" + hs);
      System.out.println("==异常通知==");
   }

}

4.XML里切点,切面

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
   <!--1.启动Spring注解-->
   <context:annotation-config></context:annotation-config>
   <!--2.扫描-->
   <context:component-scan base-package="com.hs"/>
   <!--Spring提供了多种AOP的实现方式,但是我们只用第三方的AOP标准-->
   <!--3.启动AOP注解:false是使用默认的java代理,true是使用CGLIB代理-->
   <aop:aspectj-autoproxy proxy-target-class="true"/>

   <!--4.AOP的XML配置方式,false是使用默认的java代理,true是使用CGLIB代理-->
   <!--实例化那个类,在切面引用的时候好用-->
   <bean id="logger" class="com.hs.service.aspect.Logger"/>
   <bean id="logger111" class="com.hs.service.aspect.Logger"/>
   <aop:config proxy-target-class="true">
      <!--定义切点,可以把切点放在外面作为公共的,注意pointcut aspect的顺序,对应注解版的@PointCut(value = "execution(* com.hs..service.*Service.*(..))")-->
      <aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>

      <!--定义切面,对应注解版的@Aspect,order,定义切面的执行顺序,不写默认为从上到下执行-->
      <aop:aspect ref="logger111" order="2">
         <!--定义切点,对应注解版的@PointCut(value = "execution(* com.hs..service.*Service.*(..))")-->
         <!--<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>-->
         <aop:before method="test01" pointcut-ref="servicePointCut"/>
      </aop:aspect>
      <!--定义切面,对应注解版的@Aspect-->
      <aop:aspect ref="logger" order="1">
         <!--定义切点,对应注解版的@PointCut(value = "execution(* com.hs..service.*Service.*(..))")-->
         <!--<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>-->
         <aop:before method="test05" pointcut-ref="servicePointCut"/>
      </aop:aspect>
   </aop:config>

</beans>

首先得实例化

<bean id="logger" class="com.hs.service.aspect.Logger"/>

切点:

<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>

切面:

<aop:aspect ref="logger111" order="2">
   <!--定义切点,对应注解版的@PointCut(value = "execution(* com.hs..service.*Service.*(..))")-->
   <!--<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>-->
   <aop:before method="test01" pointcut-ref="servicePointCut"/>
</aop:aspect>

测试:

package com.hs.test;

import com.hs.service.ArithmeticService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ArithmeticServiceTest {
   private ArithmeticService arithmeticService;
   private ApplicationContext ac;

   @Before
   public void init() {
      this.ac = new ClassPathXmlApplicationContext("beans.xml");
      this.arithmeticService = this.ac.getBean("arithmeticServiceImpl", ArithmeticService.class);
   }

   @Test
   public void testAddMethod() {
      int result = this.arithmeticService.div(2,1);
      System.out.println("运行的结果:"+ result);
   }
}