Spring技术总结03-Aop
一、什么是Aop
AOP:Aspect Oriented Programming面向切面编程。
AOP利用的是一种称为”横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为”Aspect”,即切面。所谓”切面”,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
AOP技术包含了切点表达式和增强方法的知识点。
二、切点表达式和增强方法
增强方法用于获取调用切面类的类信息,可以根据其信息进行添加独特的功能。
1.增强方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
@Component @Aspect @Order(15) public class LogAdivce {
@Before("execution(* com.ldy.service.impl.*.*(..))") public void before(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); System.out.println("方法参数列表:"+ Arrays.toString(args)); String name = joinPoint.getSignature().getName(); System.out.println("方法名称:"+ name); int modifiers = joinPoint.getSignature().getModifiers(); String modifer = Modifier.toString(modifiers); System.out.println("访问修饰符:"+ modifer); String className = joinPoint.getTarget().getClass().getName(); System.out.println("方法所属类:"+className);
} @After("execution(* com.ldy.service.impl.*.*(..))") public void after(){
} @AfterReturning(value = "execution(* com.ldy.service.impl.*.*(..))", returning = "result") public void afterReturning(Object result){ System.out.println("方法返回值:"+result); }
@AfterThrowing(value = "execution(* com.ldy.service.impl.*.*(..))",throwing = "throwable") public void afterThrowing(Throwable throwable){ System.out.println("方法异常对象:"+ throwable); }
}
|
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
@SpringJUnitConfig(value = Config.class) public class MyTest2 {
@Autowired public DemoService demo; @Autowired public Calculate calculate; @Test public void test01(){
int div = demo.div(1, 2); System.out.println("div=" + div);
int add = calculate.add(1, 2); System.out.println("add="+add); } }
|
2.切点表达式
切点表达式语法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
|
三、依赖和注解介绍
aspectj依赖
在新的子类工程的pom文件里添加aspectj依赖
1 2 3 4 5
| <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>6.1.12</version> </dependency>
|
注解介绍
1.@Aspect
作用于类上,声明该类为切面类
2.@Component
作用于类上,使得该切面类能放到ioc容器
3.@Order
作用于类上,用于声明切面类的优先级,数字越小级别越优先
4.@Pointcut
@Pointcut作用于空方法上,为其他方法提供切点表达式。
4.切面类的方法上的注解
1 2 3 4 5 6
| * 使用注解配置 * 前置 @Before * 后置 @AfterReturning * 最后 @After * 异常 @AfterThrowing * 环绕 @Around
|
1 2
| @Pointcut("execution(* com.ldy..*.*(..))") public void pc(){}
|
这些注解可以指定切点表达式,也可以引用本类或其他类的切点表达式。
直接指定
1
| @After("execution(* com.ldy.service.impl.*.*(..))")
|
引用本类的切点
1 2 3 4 5 6 7
| @Pointcut("execution(* com.ldy..*.*(..))") public void pc(){}
@Before("pc()") public void before(){ System.out.println("事务开启"); }
|
引用其他类中的切点表达式
1 2 3 4 5
| @After("com.ldy.pointcut.MyPointcut.all())") public void after(){ System.out.println("事务结束"); }
|
被引用的切点类
1 2 3 4 5 6 7 8
| @Component @Aspect public class MyPointcut { @Pointcut("execution(* *..impl.*.*(..))") public void impl(){} @Pointcut("execution(* com.ldy..*.*(..))") public void all(){} }
|
5.@EnableAspectJAutoProxy
作用于配置类上面,用于开启Aspectj注解支持
四、实操
简单实操如下
1.配置类
1 2 3 4 5 6 7
| @Configuration @ComponentScan(value={"com.ldy.service", "com.ldy.advice","com.ldy.pointcut"})
@EnableAspectJAutoProxy public class Config {
}
|
@EnableAspectAutoProxy用于开启Aspectj的注解支持
2.切面类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
public class Myaop { @Before("execution(* com.ldy.service.impl.*.*(..))") public void start(){ System.out.println("方法开始了"); }
@After("execution(* com.ldy.service.impl.*.*(..))") public void end(){ System.out.println("方法结束了"); } @AfterThrowing("execution(* com.ldy.service.impl.*.*(..))") public void error(){ System.out.println("方法报错了"); }
@AfterReturning("execution(* com.ldy.service.impl.*.*(..))") public void afterReturning(){
} }
|
3.Service类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.ldy.service.impl;
import com.ldy.service.DemoService; import org.springframework.stereotype.Service;
@Service public class Demo implements DemoService {
@Override public int div(int a, int b) { return a - b; }
@Override public int chu(int a, int b) { return a/b; } }
|
4.测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class MyTest { @Test public void demo01(){ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class); DemoService demo = applicationContext.getBean("demo", DemoService.class); int div = demo.div(1, 2); System.out.println("div=" + div);
}
public void demo02(){
}
}
|
五、Aop的实现原理
2024/12/6 突然想起aop的实现原理
静态代理和动态代理可参考以下文章,有空再用自己的语言整理整理
AOP的实现原理 —— 静态代理 和 动态代理( Spring AOP)_aspectj 静态代理-CSDN博客