AOP开发快速入门

基于XML的AOP开发

1.操作流程

① 导入AOP相关的坐标
② 创建目标接口和目标类
③ 创建切面类(内部有增强方法)
④ 将目标类和切面类的对象创建权交给Spring
⑤ 在applicationContext中配置织入关系
⑥ 测试代码

2.XML配置AOP详解

1)快速入门:
① 首先我们先在pom.xml里面导入AOP相关的坐标

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
    	<artifactId>spring-context</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
        <grouId>org.aspectj</grouId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.4</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
    </dependency>
</dependencies>

​ ② 然后我们编写目标类和目标方法

package Demo.XML.AOP.Impl;

import Demo.XML.AOP.Target;

public class TargetImpl implements Target {

    public void say() {
        System.out.println("我是张三...");
    }
}

​ ③编写切面方法

package Demo.XML.AOP;

public class Advice {
    public void before(){
        System.out.println("你好!!!");
    }

    public void afterReturning(){
        System.out.println("你好啊,张三。我是李四。");
    }
}

​ ④测试代码

package Demo.XML.AOP;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        Target target = (Target) app.getBean("target");
        target.say();
    }
}

​ ⑤配置Spring容器

<?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="Demo.XML.AOP.Impl.TargetImpl"></bean>

        <bean id="myAspect" class="Demo.XML.AOP.Advice"></bean>

        <aop:config>
                <aop:aspect ref="myAspect">
                        <aop:before method="before" pointcut="execution(public void Demo.XML.AOP.Impl.TargetImpl.say())"/>

                        <aop:after-returning method="afterReturning" pointcut="execution(public void Demo.XML.AOP.Impl.TargetImpl.say())"/>
                </aop:aspect>
        </aop:config>

</beans>

2)切点表达式的写法:

​ 表达式的语法如下:

execution([修饰符]返回值类型 包名.类名.方法名(参数))
  • 访问修饰符可以省略

  • 返回值类型,包名,类名,方法名可以使用*来表示任意的

  • 包名与类名之间的一个点,代表当前包下的类,两个点…代表当前包下及其子包下的类

  • 参数列表可以使用两个点…来表示任意个数以及任意类型的参数列表
    例如:

    execution(public void Demo.XML.AOP.Impl.TargetImpl.*(..))
    

3)通知的类型:

​ 通知的配置语法:

<aop:通知类型 method="切面类中方法名" pointcut="切点表达式"></aop:通知类型>
名称 标签 说明
前置通知 <aop:before> 用于配置前置通知。指定增强的方法在切入点方法之前执行
后置通知 <aop:after-returning> 用于配置后置通知。指定增强的方法在切入点方法之后执行
环绕通知 <aop:around> 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行
异常抛出通知 <aop:throwing> 用于配置异常抛出通知。指定增强的方法在出现异常时执行
最终通知 <aop:after> 用于配置最终通知。无论增强方式执行是否有异常,都会执行

​ 这里我们需要注意的是环绕通知的写法

//Proceeding JoinPoint: 正在执行的连接点也就是我们所说的切点
public Object around(PreceedingJoinPoint pjp) throws Throwable{
    System.out.println("环绕前...");
    Object proceed = pjp.proceed();
    System.out.println("环绕后...");
    return proceed;
}

4)切点表达式的抽取:

​ 当我们对多个切点使用相同的切点表达式进行增强的话,我们可以将切点表达式进行抽取,在增强中使用 pointcut-ref属性来替代原来的pointcut属性,这样便于我们后期进行代码的维护。

<aop:config>
    <aop:aspect ref="myAspect">
        <aop:pointcut id="myPointcut" expression="execution(* Demo.XML.Impl.TargetImpl.*(..))"/>
        <aop:before method="before" pointcut-ref="myPointcut"></aop:before>
    </aop:aspect>
</aop:config>

3.XML配置AOP总结

  • 织入配置

    <aop:config>
        <aop:aspect ref="切面类">
            <aop:before method="通知方法名称" pointcut="切点表达式"></aop:before>
        </aop:aspect>
    </aop:config>
    
  • 通知的类型分为前置通知,后置通知,环绕通知,异常抛出通知,最终通知

  • 切点表达式的写法:

    execution([修饰符]返回值类型 包名.类名.方法名(参数名))
    

基于注解的AOP开发

1.操作流程

① 创建目标接口和目标类,其内部有切点
② 创建切面类,其内部有增强方法
③ 将目标类和切面类的对象创建权交给spring
④ 在切面类中使用注解配置织入关系
⑤ 在配置文件中开启组件扫描和AOP的自动代理
⑥ 测试代码

2.注解配置AOP详解

1)快速入门:
① 创建目标类和目标方法

package Demo.XML.AOP.Impl;

import Demo.XML.AOP.Target;

public class TargetImpl implements Target {

    public void say() {
        System.out.println("我是张三...");
    }
}

​ ② 创建切面类,其内部有增强方法

package Demo.XML.AOP;

public class Advice {
    public void before(){
        System.out.println("你好!!!");
    }

    public void afterReturning(){
        System.out.println("你好啊,张三。我是李四。");
    }
}

​ ③ 将目标类和切面类的对象创建权交给spring

<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"
       xmlns:context="http://www.springframework.org/schema/context"
       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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <bean id="target" class="Demo.XML.AOP.Impl.TargetImpl"></bean>

        <bean id="myAspect" class="Demo.XML.AOP.Advice"></bean>
</beans>

​ ④ 在切面类中使用注解配置织入关系(也就是添加注解)

package Demo.XML.AOP;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class Advice {
    @Before("execution(public void Demo.XML.AOP.Impl.TargetImpl.say())")
    public void before(){
        System.out.println("你好!!!");
    }
    @AfterReturning("execution(public void Demo.XML.AOP.Impl.TargetImpl.say())")
    public void afterReturning(){
        System.out.println("你好啊,张三。我是李四。");
    }
    @Around("execution(public void Demo.XML.AOP.Impl.TargetImpl.say())")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("你好啊");
        Object proceed = pjp.proceed();
        System.out.println("我是李四");
        return proceed;
    }
}

​ ⑤ 在配置文件中开启组件扫描和AOP的自动代理

<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <bean id="target" class="Demo.XML.AOP.Impl.TargetImpl"></bean>

        <bean id="myAspect" class="Demo.XML.AOP.Advice"></bean>
<!--        组件扫描-->
        <context:component-scan base-package="Demo.XML.AOP"></context:component-scan>
<!--        aop自动代理-->
        <aop:aspectj-autoproxy/>
</beans>

​ ⑥ 测试代码

package Demo.XML.AOP;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        Target target = (Target) app.getBean("target");
        target.say();
    }
}

2)注解通知的类型:
通知配置的基本语法:@通知注解(“切点表达式”)

名称 注解 说明
前置通知 @Before 用于配置前置通知。指定增强的方法在切入点方法之前执行
后置通知 @AfterReturning 用于配置后置通知。指定增强的方法在切入点方法之后执行
环绕通知 @Around 用于配置环绕通知。 指定增强的方法在切入点方法之前和之后都执行
异常抛出通知 @AfterThrowing 用于配置异常抛出通知。指定增强的方法在出现异常时执行
最终通知 @After 用于配置最终通知。无论增强方法执行是否有异常都会执行

3)注解通知的类型:
通过上面的步骤我也不能发现一个问题,就是切点表达式复用的问题,与xml配置aop一样我们也可以把切点表达式抽取出来。
抽取方法:
在切面类中定义一个切点表达式的方法。在该方法上面使用@Pointcut注解定义切点表达式,然后在在增强注解中进行引用,具体代码如下:

package Demo.XML.AOP;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect
public class Advice {
    @Before("Advice.mypoint()")
    public void before(){
        System.out.println("你好!!!");
    }
    @AfterReturning("Advice.mypoint()")
    public void afterReturning(){
        System.out.println("你好啊,张三。我是李四。");
    }
    @Around("Advice.mypoint()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("你好啊");
        Object proceed = pjp.proceed();
        System.out.println("我是李四");
        return proceed;
    }
    @Pointcut("execution(public void Demo.XML.AOP.Impl.TargetImpl.say())")
    public void mypoint(){}
}

3.基于注解配置AOP总结

基于注解方式的aop开发步骤

  1. 使用@Aspect标注切面类

  2. 使用@通知注解标注通知方法

  3. 在配置文件中配置aop自动代理

    <aop:aspectj-autoproxy/>
    

猜你喜欢

转载自blog.csdn.net/qq_35540187/article/details/107432103