基于xml的AOP开发

1. 开发的步骤

(1)导入AOP相关坐标

在pom.xml中

(2)创建目标接口和目标类(内部有切点)

(3)创建切面类(内部有增强方法)

(4)将目标类和切面类的对象创建权交给spring

(5)在applicationContext.xml中配置织入关系

(6)测试代码

案例:

 (1)导入AOP相关坐标,pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.company</groupId>
    <artifactId>spring_aop</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

(2)创建目标接口(TargetInterface)和目标类(Target),切点是save()方法

TargetInterface.java

package com.company.aop;

public interface TargetInterface {
    void  save();
}

Target.java

package com.company.aop;

public class Target implements TargetInterface {
    public void save() {
        System.out.println("save running ...");
    }
}

(3)创建切面类,增强方法是before()方法

package com.company.aop;

public class MyAspect {

    public void before() {
        System.out.println("前置增强........");
    }
}

(4)将目标对象和切面对象的创建权交给spring,在applicationContext.xml中配置,Spring的很多功能首要条件就是这些bean要放到容器中,spring才能在容器中拿出对象,进行相应的操作。

 (5)在applicationContext.xml中配置织入关系,method="before"是myAspect的before()方法

完整版的applicationContext.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <!--目标对象-->
    <bean id="target" class="com.company.aop.Target"></bean>
    <!--切面对象-->
    <bean id="myAspect" class="com.company.aop.MyAspect"></bean>
    <!--配置织入:告诉spring框架,哪些方法(切点)需要进行哪些增强(前置,后置)-->
    <aop:config>
        <!-- 声明切面-->
        <aop:aspect ref="myAspect">
        <!--切面:切点+通知-->
            <aop:before method="before" pointcut="execution(public void com.company.aop.Target.save())"></aop:before>
        </aop:aspect>
    </aop:config>

</beans>

 (6)测试 ,AopTest.java

package com.company.test;

import com.company.aop.TargetInterface;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
    @Autowired
    private TargetInterface targetInterface;
    @Test
    public void test1() {
        targetInterface.save();
    }

}

  运行结果:

2. 切点表达式的写法

<aop:before method="before" pointcut="execution(public void com.company.aop.Target.save())"></aop:before>

(1)访问修饰符可以省略

(2)返回值类型、包名、类名、方法名可以使用星号*代表任意

(3)包名与类名之间一个点.代表当前包下的类,两个点..表示当前包及其子包下的类

(4)参数列表可以使用两个点..表示任意个数,任意类型的参数列表

例如:

excution(public void com.company.aop.Target.method())

excution(void com.company.aop.Target.*(..))  *表示任意方法,(..)表示参数任意个

excution(* com.company.aop.*.*(..))  aop包下的任意类,任意方法,这种形式最常用

excution(* com.company.aop..*.*(..))  aop包及其子包下的任意类,任意方法

excution(* *..*.*(..))

上面的可以改成这样

<aop:before method="before" pointcut="execution(* com.company.aop.*.*(..))"></aop:before>

 3. 通知的类型

 

 

3.1. 后置通知 

在原来的切面类中加如后置增强方法

MyAspect.java

package com.company.aop;

public class MyAspect {

    public void before() {
        System.out.println("前置增强........");
    }
    public void afterReturning() {
        System.out.println("后置增强");
    }
}

  再在applicationContext.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <!--目标对象-->
    <bean id="target" class="com.company.aop.Target"></bean>
    <!--切面对象-->
    <bean id="myAspect" class="com.company.aop.MyAspect"></bean>
    <!--配置织入:告诉spring框架,哪些方法(切点)需要进行哪些增强(前置,后置)-->
    <aop:config>
        <!-- 声明切面-->
        <aop:aspect ref="myAspect">
        <!--切面:切点+通知-->
            <aop:before method="before" pointcut="execution(* com.company.aop.*.*(..))"></aop:before>
            <aop:after-returning method="afterReturning" pointcut="execution(* com.company.aop.*.*(..))"></aop:after-returning>
        </aop:aspect>
    </aop:config>

</beans>

执行AopTest.java

运行结果:

 3.2. 环绕通知

在原来的切面类中加入环绕通知方法

MyAspect.java

package com.company.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {

    public void before() {
        System.out.println("前置增强........");
    }
    public void afterReturning() {
        System.out.println("后置增强");
    }

    // ProceedingJoinPoint 正在执行的连接点 === 切点
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕前增强.....");
        // 切点方法
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("环绕后增强.....");
        return proceed;
    }

}

  再在applicationContext.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <!--目标对象-->
    <bean id="target" class="com.company.aop.Target"></bean>
    <!--切面对象-->
    <bean id="myAspect" class="com.company.aop.MyAspect"></bean>
    <!--配置织入:告诉spring框架,哪些方法(切点)需要进行哪些增强(前置,后置)-->
    <aop:config>
        <!-- 声明切面-->
        <aop:aspect ref="myAspect">
        <!--切面:切点+通知-->
<!--            <aop:before method="before" pointcut="execution(* com.company.aop.*.*(..))"></aop:before>-->
<!--            <aop:after-returning method="afterReturning" pointcut="execution(* com.company.aop.*.*(..))"></aop:after-returning>-->
            <aop:around method="around" pointcut="execution(* com.company.aop.*.*(..))"></aop:around>
        </aop:aspect>
    </aop:config>

</beans>

执行AopTest.java

运行结果:

 3.3 异常抛出通知

在MyAspect.java中加入异常抛出增强方法

package com.company.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {

    public void before() {
        System.out.println("前置增强........");
    }
    public void afterReturning() {
        System.out.println("后置增强");
    }

    // ProceedingJoinPoint 正在执行的连接点 === 切点
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕前增强.....");
        // 切点方法
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("环绕后增强.....");
        return proceed;
    }

    public void afterThrowing() {
        System.out.println("异常抛出增强.....");
    }

}

  异常抛出的是目标对象中的异常,因此在Target中构造异常

Target.java

package com.company.aop;

public class Target implements TargetInterface {
    public void save() {
        int i = 1/0;
        System.out.println("save running ...");
    }
}

  再在applicationContext.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <!--目标对象-->
    <bean id="target" class="com.company.aop.Target"></bean>
    <!--切面对象-->
    <bean id="myAspect" class="com.company.aop.MyAspect"></bean>
    <!--配置织入:告诉spring框架,哪些方法(切点)需要进行哪些增强(前置,后置)-->
    <aop:config>
        <!-- 声明切面-->
        <aop:aspect ref="myAspect">
        <!--切面:切点+通知-->
<!--            <aop:before method="before" pointcut="execution(* com.company.aop.*.*(..))"></aop:before>-->
<!--            <aop:after-returning method="afterReturning" pointcut="execution(* com.company.aop.*.*(..))"></aop:after-returning>-->
            <aop:around method="around" pointcut="execution(* com.company.aop.*.*(..))"/>
            <aop:after-throwing method="afterThrowing" pointcut="execution(* com.company.aop.*.*(..))"/>
        </aop:aspect>
    </aop:config>

</beans>

执行AopTest.java

运行结果:

3.4 最终通知

在MyAspect.java中加入最终增强方法

package com.company.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {

    public void before() {
        System.out.println("前置增强........");
    }
    public void afterReturning() {
        System.out.println("后置增强");
    }

    // ProceedingJoinPoint 正在执行的连接点 === 切点
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕前增强.....");
        // 切点方法
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("环绕后增强.....");
        return proceed;
    }

    public void afterThrowing() {
        System.out.println("异常抛出增强.....");
    }

    public void after() {
        System.out.println("最终增强.....");
    }

}

  再在applicationContext.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <!--目标对象-->
    <bean id="target" class="com.company.aop.Target"></bean>
    <!--切面对象-->
    <bean id="myAspect" class="com.company.aop.MyAspect"></bean>
    <!--配置织入:告诉spring框架,哪些方法(切点)需要进行哪些增强(前置,后置)-->
    <aop:config>
        <!-- 声明切面-->
        <aop:aspect ref="myAspect">
        <!--切面:切点+通知-->
<!--            <aop:before method="before" pointcut="execution(* com.company.aop.*.*(..))"/>-->
<!--            <aop:after-returning method="afterReturning" pointcut="execution(* com.company.aop.*.*(..))"/>-->
            <aop:around method="around" pointcut="execution(* com.company.aop.*.*(..))"/>
            <aop:after-throwing method="afterThrowing" pointcut="execution(* com.company.aop.*.*(..))"/>
            <aop:after method="after" pointcut="execution(* com.company.aop.*.*(..))"/>
        </aop:aspect>
    </aop:config>

</beans>

运行结果:

 4.切点表达式抽取

当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用pointcut-ref属性代替pointcut属性来引用抽取后的切点表达式

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <!--目标对象-->
    <bean id="target" class="com.company.aop.Target"></bean>
    <!--切面对象-->
    <bean id="myAspect" class="com.company.aop.MyAspect"></bean>
    <!--配置织入:告诉spring框架,哪些方法(切点)需要进行哪些增强(前置,后置)-->
    <aop:config>
        <!-- 声明切面-->
        <aop:aspect ref="myAspect">
            <!--抽取切点表达式-->
            <aop:pointcut id="myPointcut" expression="execution(* com.company.aop.*.*(..))"/>
            <aop:around method="around" pointcut-ref="myPointcut"/>
            <aop:after method="after" pointcut-ref="myPointcut"/>
        </aop:aspect>
    </aop:config>

</beans>
原文地址:https://www.cnblogs.com/GumpYan/p/14188890.html