动 态 代 理 : 指 在 程 序 运 行 期 间 动 态 的 将 某 段 代 码 切 入 到 指 定 方 法 指 定 位 置 进 行 运 行 的 编 程 方 式 \color{blue}{ 动态代理:指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式} 动态代理:指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式
案例
MathCalculator.div()方法执行时打印执行之前、结束之后等等环节的日志
实
现
步
骤
:
\color{red}{ 实现步骤:}
实现步骤:
1.导入aop模块 可以直接在pom当中引入spring-aspects
2.定义一个业务逻辑类(MathCalculator) 在业务逻辑运行的时候将日志进行打印(方法执行之前、运行结束、出现异常等等)
3.定义一个日志切面类(LogAspects) 切面类里面的方法需要动态的感知MathCalculator.div()运行到哪里然后执行
3.1通知方法
前置通知(@Before):logStart:在目标方法(div)运行之前运行
后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
4.给切面类的目标方法标注何时何地运行(通知注解)
5.将切面类+业务逻辑类都加入到容器当中
6.告诉Spring容器那个是切面类--切面类上面加注解@Aspect (这个注解是必加的)
7.在配置类当中加@EnableAspectJAutoProxy注解--开启基于注解的Aop模式
代码实现
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
public class MathCalculator {
public int div(int i, int j) {
System.out.println("MathCalculator...div...");
return i / j;
}
}
**/
//告诉Spring当前类是一个切面类
@Aspect
public class LogAspects {
/**
* 抽取公共的切入点表达式
* 1:本类引用
* 2:其他切面的引用
*/
@Pointcut("execution(public int com.ly.springannotation.aop.MathCalculator.*(..))")
public void pointCut() {
}
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
System.out.println("" + joinPoint.getSignature().getName() + "运行。。。@Before:参数列表是:{" + Arrays.asList(args) + "}");
}
@After("com.ly.springannotation.aop.LogAspects.pointCut()")
public void logEnd(JoinPoint joinPoint) {
System.out.println("" + joinPoint.getSignature().getName() + "结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value = "pointCut()", returning = "result")
public void logReturn(JoinPoint joinPoint, Object result) {
System.out.println("" + joinPoint.getSignature().getName() + "正常返回。。。@AfterReturning:运行结果:{" + result + "}");
}
@AfterThrowing(value = "pointCut()", throwing = "exception")
public void logException(JoinPoint joinPoint, Exception exception) {
System.out.println("" + joinPoint.getSignature().getName() + "异常。。。异常信息:{" + exception + "}");
}
}
配置类
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
//业务逻辑类加入容器中
@Bean
public MathCalculator calculator() {
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects() {
return new LogAspects();
}
}
测试
public class IOCTest_AOP {
@Test
public void test() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
MathCalculator calculator = (MathCalculator) applicationContext.getBean("calculator");
calculator.div(10, 5);
applicationContext.close();
}
}
测试结果