详述SpringAOP实现及执行过程(上)

一、AOP概念

AOP(Aspect Oriented Programming 面向切面编程)是一种通过运行期动态代理实现代码复用的机制,是对传统OOP(Object Oriented Programming,面向对象编程 )的补充。目前,Aspectj是Java社区里最完整最流行的AOP框架,在Spring 2.0以上版本中可以通过Aspectj注解或基于XML配置AOP。
AOP的重要作用是增强对应的普通方法,提高方法中代码的复用性,具体场景可参考相关文章JDK动态代理

二、Aspectj注解实现AOP

1、添加jar包

在这里插入图片描述

2、xml文件中配置Spring Bean

<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	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-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<context:component-scan base-package="com.jd"></context:component-scan>
	<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
</beans>

其中“context:component-scan”作用是扫描com.jd包下所有注解;
aop:aspectj-autoproxy”作用是设置Spring自动为有@Aspect注解的对象产生动态代理对象,**proxy-target-class=“false”**为采用JDK动态代理,proxy-target-class="true"代表采用CGLib动态代理。
注意:
1、从Spring 3.2开始spring-core-xxx.jar包已集成CGLib和ASM 相关jar包,所以Spring工程不需再额外引入这些jar包;
2、即使proxy-target-class设置为false,如果目标类没有声明接口,则Spring将自动使用CGLib生成代理对象。

3、定义一个用@Aspect修饰的切面类

@Before前置增强
package com.zzu.calculator;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect//将该类声明为切面类
@Component
public class CalculatorAspect {

	@Before("execution(public int com.jd.calculator.CalculatorService.mul(..))")
	public void before(JoinPoint jp) {
		Object obj = jp.getTarget();
		Object[] args = jp.getArgs();
		System.out.println(obj.getClass().getName()+":The mul method begins.");
		System.out.println(obj.getClass().getName()+":Parameters of the mul method: ["+args[0]+","+args[1]+"]");
	}
}

Before注解为前置增强,其中的参数为切入点表达式(“execution(public int com.jd.calculator.CalculatorService.mul(…))”),是在目标方法执行之前执行。

sevice层代码:

package com.zzu.calculator;

import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService {

	@Override
	public int mul(int a, int b) {
		int result = a*b;
		return result;
	}

	@Override
	public int div(int a, int b) {
		int result = a/b;
		return result;
	}
}

Test类

package com.zzu.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zzu.calculator.ICalculatorService;

public class Test {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		ICalculatorService calculator = applicationContext.getBean(ICalculatorService.class);
		int result = calculator.mul(4, 2);
		System.out.println("——>"result);
		applicationContext.close();
	}
}

结果

com.jd.calculator.CalculatorService:The mul method begins.
com.jd.calculator.CalculatorService:Parameters of the mul method: [4,2]
——>8
@After后置增强
	@After("execution(public int com.jd.calculator.CalculatorService.mul(..))")
	public void after(JoinPoint jp) {
		Object target=jp.getTarget();
		String methodName = jp.getSignature().getName();
		System.out.println(target.getClass().getName()+":The "+methodName+" method ends.");
	}

sevice类与Test类同上

执行结果

com.jd.calculator.CalculatorService:The mul method ends.
——>8

三、执行过程

  1. XML配置文件添加autoproxy标签

  2. Spring寻找带有@Aspect的类,例如上面的CalculatorAspect类

  3. 扫描带有@Aspect的类中带有 @Before,@After,@AfterReturning,@Around,@AfterThrowing 等注解的方法,得到该注解,并根据不同的注解判断是对应的是哪一种增强方式

  4. 获取表达式,例如上面的(“execution(public int com.jd.calculator.CalculatorService.mul(…))”)这个表达式就是指定需要被增强的方法

  5. 检查Spring能扫描到的所有类,找到表达式匹配的方法对应的类

  6. 为该类创建动态代理对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值