彻底弄懂 Spring AOP 中的概念

原创
07/25 15:24
阅读数 16

谈到Spring,相信只要从事Java开发的同学都知道Spring的两大核心:AOP 和IOC, 本文只谈AOP。

AOP的概念,相信很多人面试都被问到过,但每次都弄的不太清楚,比如: 什么是切面,什么是增强,什么是切点...

面对如此晦涩难懂的名词,本文尝试通过代码帮助大家理解并记忆这些概念,为了便于理解,这里使用xml配置方式,实际工作中用的比较多的还是注解方式。话不多说,撸代码:

  1. 导入依赖:
 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
    </dependencies>
  1. 编写配置文件 beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
 
        <bean id="userService" class="top.lovelily.spring.service.impl.UserServiceImpl"/>
        <bean id = "helloArroundAdvice" class="top.lovelily.spring.aop.HelloAroundAdvice"/>
        <bean id ="logAspect" class="top.lovelily.spring.aop.LogAspect"/>
 
        <aop:config>
              <!--第一种:aspect方式配置切面-->
                <aop:aspect id="logAspect" ref="logAspect">
                        <!--execution(返回值 包名.接口名.方法名(参数)-->
                        <!--execution(User top.lovelily.spring.service.UserService.get())-->
                        <aop:pointcut id="serviceOperation"
                                      expression="execution(* top.lovelily.spring.service.*.*(..))"/>
 
                        <aop:around
                                pointcut-ref="serviceOperation"
                                method="doAroundLog"/>
 
                </aop:aspect>
                <!--第一种:aspect方式配置切面-->
                
                <!--第二种:advisor方式配置切面-->
                <aop:pointcut id="myPointcut" expression="execution(* top.lovelily.spring.service.*.*(..))"/>
                <aop:advisor advice-ref="helloArroundAdvice" pointcut-ref="myPointcut"/>
                <!--第二种:advisor方式配置切面-->
        </aop:config>
</beans>

  1. 编写切面类 LogAspect.java

public class LogAspect {
    public Object doAroundLog(ProceedingJoinPoint joinPoint) {
        System.out.println("begin...");
        try {
            Object result = joinPoint.proceed();
 
            // execution(void top.lovelily.spring.service.UserService.save(User))
            System.out.println(joinPoint);
            // top.lovelily.spring.service.impl.UserServiceImpl@3e3047e6
            System.out.println(joinPoint.getTarget());
 
            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("end...");
        return null;
    }
}

  1. 编写测试类
public class TestAop {
    public static void main(String[] args) {
        UserService userService1 = new UserServiceImpl();
        System.out.println(userService1 instanceof UserServiceImpl); // true
        System.out.println(userService1 instanceof UserService);    //true
 
        System.out.println("------------------------------------");
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
        Object bean = context.getBean("userService");
        System.out.println(bean instanceof Advised); // true
 
        System.out.println(bean instanceof UserService); // true
        
        UserService userService = (UserService) bean;
 
        User user = new User();
       // userService.save(user);
        User user1 = userService.get();
        System.out.println(user1);
 
    }
}

通过代码运行结果,总结AOP相关概念:

  • joinpoint:连接点,程序执行时的某个特定的点,在Spring中就是某一个方法的执行,如程序中打印的execution(User top.lovelily.spring.service.UserService.get())

  • pointcut:切点,方法的集合,包含多个joinpoint,通常会有通配符,xml配置文件中的execution(* top.lovelily.spring.service..(..))

  • aspect:切面,可以横跨多个class,封装了一些操作(advice), 就是个,封装了具体要插入的操作,比如LogAspect.java记录了开始结束日志。

  • advice:通知,在切点执行的操作,before, after,aroud:具体要添加的操作(方法), 就是个方法,比如LogAspect.java中的doAroundLog方法

  • advisor:通知器,从advisor方式配置切面方式的配置中可以看出,就是pointcut和advice的适配

  • advised: 也称为目标对象,或者说被代理对象,即我们的bean


如果觉得还不错的话,关注、分享、在看, 原创不易,且看且珍惜~

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部