Spring AOP配置(三)

在这里插入图片描述

一:Spring AOP的简介

AOP 意思为面向切面编程,是 OOP 的延续,底层是由动态代理技术实现的!

作用:在程序运行期间,在不修改源码的情况下对目标方法进行功能增强

优势:减少重复代码,提高开发效率,并且便于维护

1.1:jdk 的动态代理
1.2:cglib的动态代理

注:cglib动态代理: 在高版本的spring,已经不需要额外导jar坐标了,已经集成在spring-core中了!

二:Spring AOP中的术语
Aop的相关概念!
1.Target(目标对象)
2.Proxy(代理对象)
3.joinpoint(连接点):可以被增强的方法叫做连接点!
4.pointcut(切点):被增强的方法
5.Advice(通知/增强): 所谓通知是指拦截到Joinpoint之后要做的事情就是通知
6.Aspect(切面): 是切点+通知
7.Weaving(织入): 是切点+通知结合的过程!!!

注:连接点和切点的关系,就好像所有的女生都可以嫁人这是连接点,但是只有嫁过人的女生才是切点
三:基于XML的AOP开发
步骤: 
1.导入spring-aop和aspectjweaver的jar坐标
2.创建目标接口和目标类(内部有切点)
3.创建切面类
4.将目标类和切面类交给spring进行管理
5.在spring配置中,配置AOP
6.使用spring集成junit的方式来测试
  • 1、 导入spring-aop和aspectjweaver的jar坐标

注: spring-context 中有spring-aop,但是还需要aspectjweaver

<dependencies>
    <!--AOP: sprint-aop和aspectj-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.13</version>
    </dependency>
</dependencies>
  • 2、创建目标接口和目标类(内部有切点)

  • 目标接口

package com.wzj.aop.xml;

public interface TargetInterface {

    void save();
}
  • 目标类
package com.wzj.aop.xml;

public class Target implements TargetInterface{
    @Override
    public void save() {
        System.out.println("save()...");
    }
}
  • 3、创建切面类
public class MyAspect {

    //前置通知
    public void before(){
        System.out.println("前置通知:");
    }

    //后置通知
    public void afterReturning(){
        System.out.println("后置通知:");
    }

    //环绕通知
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知前:");
        Object obj = pjp.proceed();
        System.out.println("环绕通知后:");
        return obj;
    }

    //异常抛出通知: 只有修饰的切点表达式中的切点在运行过程中抛出了异常后,才会触发!
    public void afterThrowing(){
        System.out.println("异常抛出通知");
    }

    //最终通知: 不管修饰的切点表达式,运行的时候有没有发生异常,最终都会执行,类似finally关键字
    public void after(){
        System.out.println("最终通知");
    }
}
  • 4、将目标类和切面类交给spring进行管理&配置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"
       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">

    <!--1.配置目标类-->
    <bean id="target" class="com.wzj.aop.xml.Target"></bean>
    <!--2.配置切面类: 其实就是个普通的bean,需要指定才能成为切面类,要不然spring哪知道-->
    <bean id="myAspect" class="com.wzj.aop.xml.MyAspect"></bean>

    <!--3.配置织入 = 切点+通知结合的过程, 注:需要引入aop的命名空间和xml约束-->
   <aop:config>
        <!--4.ref:指定该类为切面类, 切面 = 切点 + 通知-->
        <aop:aspect ref="myAspect">
            <!--
                5.告诉spring,哪些方法(切点)需要哪些通知/增强(5种)
                method:指定切面类中的哪个方法作为通知/增强, pointcut:指定目标对象中的哪些方法作为切点
            -->
            <aop:before method="before" pointcut="execution(* com.wzj.aop.xml.Target.*(..))"></aop:before>
            <aop:after-returning method="afterReturning" pointcut="execution(* com.wzj.aop.xml.Target.*(..))"></aop:after-returning>
            <aop:around method="around" pointcut="execution(* com.wzj.aop.xml.Target.*(..))"></aop:around>
            <aop:after-throwing method="afterReturning" pointcut="execution(* com.wzj.aop.xml.Target.*(..))"></aop:after-throwing>
            <aop:after method="after" pointcut="execution(* com.wzj.aop.xml.Target.*(..))"></aop:after>
        </aop:aspect>
   </aop:config>

</beans>
  • 5、使用spring集成junit的方式来测试

使用之前记得导入spring-test和junit的jar坐标

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopXmlModeTest {

    @Autowired
    private TargetInterface target; //依赖倒转原则

    @Test
    public void testXml(){
        target.save();
    }

}
  • 控制台
前置通知:
环绕通知前:
save()...
最终通知
环绕通知后:
后置通知:
3.6:切点表达式的抽取

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RGqSjqOV-1597070635017)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597066347316.png)]

  • 优化后
    在这里插入图片描述
3.7:通知的XML类型
  • 通知的配置语法
<aop:通知类型 method=“切面类中方法名” pointcut=“切点表达式"></aop:通知类型>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m18x7DRN-1597070635020)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597066778461.png)]

3.8:切点表达式的写法
  • 表达式语法
execution(修饰符 返回值类型 包名.类名.方法名(参数))

注:切点表达式确实就是针对方法来的,距离方法括号最近的一个是方法名,然后是类名!!

1.访问修饰符可以省略
2.返回值类型、包名、类名、方法名可以使用星号*代表任意
3.参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
4.包名与类名之间一个点.代表当前包下的类,两个点..表示当前包及其子包下的类
  • 例子
1.execution(public void com.wzj.aop.Target.method())	

表示com.wzj.aop包下的Target类的被public修饰的无参无返回值的method方法,被选中为切点!!

2.execution(void com.wzj.aop.Target.*(..))

表示com.wzj.aop.Target包下的Target类下的任意参数的无返值的方法,被选中为切入点!!

3.execution(* com.wzj.aop.*.*(..))

表示com.wzj.aop包下的所有类的所有方法!!,这点是比较常用的!!

四:基于注解的AOP开发
步骤:
1.导入spring-aop和aspectjweaver的jar坐标
2.创建目标接口和目标类(内部有切点)
3.使用@Aspect来指定切面类(内部有通知/增强),使用@Before,@AfterReturning,@Around,@AfterThrowing,@After来指定通知/增强
4.使用@Component注解的方式将目标类和切面类交给spring进行管理
5.在spring配置中,进行包扫描,和开启Aop的自动代理
6.使用spring集成junit的方式来测试
  • 1、导入spring-aop和aspectjweaver的jar坐标

参照基于xml的aop开发的第一点

  • 2、创建目标接口和目标类(内部有切点)
package com.wzj.aop.anno;

@Component
public class Target implements TargetInterface{
    @Override
    public void save() {
        System.out.println("save()...");
    }
}
public interface TargetInterface {
    void save();
}
  • 3、使用@Aspect来指定切面类(内部有通知/增强),使用@Before,@AfterReturning,@Around,@AfterThrowing,@After来指定通知/增强
@Component
@Aspect
public class MyAspect {

    @Before("execution(* com.wzj.aop.anno.Target.*(..))")
    public void before(){
        System.out.println("前置通知:");
    }

    @AfterReturning("execution(* com.wzj.aop.anno.Target.*(..))")
    public void afterReturning(){
        System.out.println("后置通知:");
    }

    @Around("execution(* com.wzj.aop.anno.Target.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知前:");
        Object obj = pjp.proceed();
        System.out.println("环绕通知后:");
        return obj;
    }

    @AfterThrowing("execution(* com.wzj.aop.anno.Target.*(..))")
    public void afterThrowing(){
        System.out.println("异常抛出通知");
    }

    @After("execution(* com.wzj.aop.anno.Target.*(..))")
    public void  after(){
        System.out.println("最终通知");
    }

}
  • 4、使用@Component注解的方式将目标类和切面类交给spring进行管理

注:类上都加了@Component注解

  • 5、在spring配置中,进行包扫描,和开启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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--使用组件扫描,将@Component这类注解实例化的bean,放到spring容器中进行管理-->
    <context:component-scan base-package="com.wzj.aop.anno"></context:component-scan>

    <!--开启Aop的自动代理,不然使用通知的时候会没有效果-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

注:默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class=“true”/>时,表示使用CGLib动态代理技术织入增强

  • 6、使用spring集成junit的方式来测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-anno.xml")
public class AopAnnoModeTest {

    @Autowired
    private TargetInterface target;

    @Test
    public void testAnno(){
        target.save();
    }

}
  • 控制台
环绕通知前:
前置通知:
save()...
环绕通知后:
最终通知
后置通知:
4.1:切点表达式的抽取

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ig0WyPW-1597070635022)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597069183633.png)]

  • 优化后
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y21WSnwm-1597070635023)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597069383378.png)]
4.2:通知的注解类型

在这里插入图片描述
来自:虽然帅,但是菜的cxy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值