Spring AOP 入门

参考博客: www.jianshu.com/p/994027425… ,个人感觉比spring实战里面要讲的好(例子举得更真实),可以看了这个再结合spring实战的AOP看。

1.什么是AOP?

面向切面编程(Aspect Oriented Programming),个人裂解面向切面编程和IOC都是一种思想。如博客链接所述,AOP的思想是将业务的核心功能和周边功能分开。 核心功能:对数据库的增删改查都属于核心功能 周边功能:性能统计、日志、事务管理 在AOP的思想中,周边功能即切面。切面和核心功能分开开发,定义为“编织”(Weaving)

2.AOP的目的

封装与业务无关,但是为业务模块所公共调用的的模块(事务处理、日志等)。减少代码量,降低耦合度,提高可维护性和可拓展性。 AOP中的概念: 1)切入点(Pointcut) Where:在什么地方做 2)通知(Advice) When+What:在什么时机做什么 3)切面(Aspect) 切入点+通知:什么时机在什么地方做什么 4)织入(Weaving) 把切面加入到对象,并创建出代理对象的过程。(由 Spring 来完成)

3.实战AOP demo:

以博客上的租房案例为准,这里再整理一下。 加入包租婆(landlord)想要通过中介把自己的房子租出去,当别人需要租这间房的时候,整体的happy path业务流程如下:

1)找到中介->2)中介带领看房->3)中介谈价格->4)包租婆来签合同->5)包租婆收房租->6)中介交钥匙

很明显,对于包租婆来说,只有4)和5)需要她参与,站在她的角度,这两个环节才是核心业务,而和中介相关的2)->3)->6)都属于政哥happy path的周边业务。这个业务理理清楚之后,开始demo。

3.1首先引包:

implementation 'org.springframework:spring-aspects:5.3.13'
复制代码

3.2创建package pojo->创建Landlord类

@Component
public class Landlord {

    public void service() {
        //包租婆:只有核心代码
        System.out.println("签合同");
        System.out.println("收房租");
    }
}
复制代码

创建中介类package aspect->Broker

@Aspect
@Component
public class Broker {

    //这个broker就是一个通知advice,专注于非核心业务代码

    //为避免每一个方法上面写全路径名,专门定义一个方法来放切入点(pointcut)
    @Pointcut("execution(* com.springaopdemo.pojo.Landlord.service())")
    public void brokerService() {
    }

    @Before("brokerService()")
    public void before() {
        //非核心功能-业务之前
        System.out.println("看租客房子");
        System.out.println("谈价格");
    }

    @After("brokerService()")
    public void after() {
        //非核心功能-业务之后
        System.out.println("交钥匙");
    }

}
复制代码

可以看出切点的编写规则: execution (* 路径.执行方法名)

*excution定义在方法名上,方法执行时触发;代表返回任意类;后面跟方法所属类的路径.方法名(参数)

在启动类上开启扫描

@SpringBootApplication
@ComponentScan({"com.springaopdemo.aspect","com.springaopdemo.pojo"})
public class SpringAoPdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringAoPdemoApplication.class, args);
    }

}
复制代码

通过xml文件对bean进行装配,创建如下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: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">

    <context:component-scan base-package="com.springaopdemo.aspect" />
    <context:component-scan base-package="com.springaopdemo.pojo" />

    <aop:aspectj-autoproxy/>
</beans>
复制代码

测试:

@SpringBootTest

public class LandlordTest {

    @Test
    public void should_get_information_from_test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Landlord landlord = context.getBean(Landlord.class);
        landlord.service();
    }

}
复制代码

运行,输出结果如下:

看租客房子
谈价格
签合同
收房租
交钥匙
复制代码

4.编写规则

除了上面使用的Before,After之外,还有3种:

AspectJ注解声明通知方法
@After 在目标方法放回or抛出异常后调用
@Before 在目标方法调用之前执行
@Around 通知方法会把目标方法封装起来,达到@After和@Before结合的效果
@AfterReturning 方法会在目标方法返回后调用
@AfterThrowing 方法会在目标方法抛出异常后调用

5.实战AOP demo_2:

demo2使用@Around注解通过环绕方法来进行通知设计

@Around("brokerService()")
public void around(ProceedingJoinPoint joinPoint) {
    System.out.println("租客看房子");
    System.out.println("谈价格");
    try {
        joinPoint.proceed();
    } catch (Throwable throwable) {
        throwable.printStackTrace();
    }
    System.out.println("交钥匙");
}
复制代码

输出结果:

租客看房子
谈价格
签合同
收房租
交钥匙
复制代码

最后总结一下,在这个demo中,谁是通知advice?谁是切点joinpiont? 通知就是broker的每个方法,切点就是路径对应的方法,二者加起来就是一个切面。 这里是一个简单的AOP的deom,现实的项目中我们可能用的比较多的就是用来打日志。

猜你喜欢

转载自juejin.im/post/7033697812277952520