spring-aop组件详解——实现Advice通知


AOP的主要用途

AOP的主要用途是在不改变目标类的情况下,对目标类添加一些额外的功能进行增强,主要原理是使用动态代理来动态的生成代理对象,在代理对象中添加额外的功能

AOP的几个重要的概念:

Joint point(连接点): 表示程序中明确定义的点,比如方法调用、成员访问、异常处理这些点都是AOP可以织入的点
Pointcut(切点): 表示AOP具体需要织入的点,也就是从Joint point(连接点)中过滤出来的一些点
Advice(增强): 表示我要对需要强入的点做什么操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码
Target(目标对象): 需要增强的具体对象
Weaving(织入): 将额外的功能添加到目标对象的过程
Aspect(切面): PointCut和Advice的组合

Advice的几个注解:

注解描述
@Before连接点前面执行,不能终止后续流程,除非抛异常
@AfterReturning连接点正常返回时执行,有异常不执行
@Around围绕连接点前后执行,也能捕获异常处理
@After连接点退出时执行,无论是正常退出还是异常退出
@AfterThrowing连接点方法抛出异常时执行

AOP前置增强范例

1:定义接口

public interface GameService {
    public void game();
}
public interface ReadService {
        public void read();
}

2:定义实现类

@Component
public class GameServiceImpl implements GameService {
	@Override
    public void game() {
        System.out.println("玩游戏");
    }
}
@Component
public class ReadServiceImpl implements ReadService {
	@Override
    public void read() {
        System.out.println("阅读书籍");
    }
}
@Component
public class SleepServiceImpl {
    public void sellp() {
        System.out.println("睡觉");
    }
}

3:定义切面类

需要引入切面注解@Aspect依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
@Aspect
@Component
public class AspectSection {

    @Before("execution(* com.xlf.test.aop.service.GameService.game(..)) || execution(* com.xlf.test.aop.serviceimpl.SleepServiceImpl.sellp(..))")
    public void action(){
        System.out.println("在干嘛");
    }

}

4:自动配置的加载类

@Configuration
@ComponentScan(basePackages = "com.xlf.test.aop")
@EnableAspectJAutoProxy
public class LifeCofig {
}

5:测试类

public class TestAop {

    @Test
    public void aopBefore(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LifeCofig.class);
        GameService gameService = context.getBean("gameServiceImpl",GameService.class);
        SleepServiceImpl sleepService = context.getBean("sleepServiceImpl",SleepServiceImpl.class);
        ReadService readService = context.getBean("readServiceImpl", ReadService.class);
        gameService.game();
        System.out.println("------------");
        sleepService.sellp();
        System.out.println("------------");
        readService.read();
    }
}

输出结果

输出结果

后置增强范例

只需要把后置增强注解@Before改为@After即可

来看看运行效果

在这里插入图片描述

Spring AOP是如何实现的

我们都知道AOP的实现方法是动态代理,就是在程序运行期间动态的为目标类创建代理,从而实现目标类的增强

Java的动态代理有两种实现方式:

JDK的动态代理
CGlib动态代理

这两种动态代理的主要区别:
JDK是通过代理类跟目标类实现同一个接口来实现代理的
CGlib是通过继承目标类来实现代理的

实现了接口的类进行增强时使用JDK的动态代理,普通类的增强使用CGlib

GameService实现了接口的类,使用的是JDK动态代理

在这里插入图片描述

SleepServiceImpl是个普通类,使用的是CBLIB动态代理

在这里插入图片描述

既然CGLIB可以实现普通类的增强,那它必然也是支持实现了接口的类的增强,因为实现了接口的类也是普通类
我们只要修改一个参数,就可以实现全部使用CGLIB动态代理

proxyTargetClass = true 表示所有类都使用CGLIB动态代理

在这里插入图片描述我们修改参数后,运行结果如下图所示

在这里插入图片描述

可以看出来,GameService是实现了接口的类,默认情况下是使用JDK动态代理,当把@EnableAspectJAutoProxy注解的proxyTargetClass属性改为true时,所有类都使用CBLIB动态代理

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值