SpringAOP实现及执行过程

文章目录

AOP实现

  • AOP(Aspect Oriented Programming 面向切面编程),是基于动态代理的实现代码复用的机制,是对传统OOP(Object Oriented Programming 面向对象编程)的补充。

新建一个计算器ICalculatorService接口

public interface ICalculatorService {
	int mul(int a, int b);
	int div(int a, int b);
}

实现这个接口

@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;
	}
}
  • 如果想要在接口实现类中的方法前后增加代码,
  1. 直接增加(过于繁琐,如果有很多方法和类工作量巨大)
  2. 动态代理工厂(JDK动态代理,cglib动态代理等),为每个需要增强的类编写一个工厂(如果多个类仍然需要写大量的代理工厂类)
  3. 借助Spring框架和注解和切入点表达式自动的为目标对象生成动态代理对象(这种方法就是对动态代理的封装)

Spring框架中提供了XML文件配置,和注解两种方式实现AOP
这里主要介绍一下Aspectj注解实现AOP

  1. 准备导入Spring框架的核心jar包(五个),然后两个支持AOP的jar包(两个)。一共需要导入7个jar包其他的jar包暂时可以不导入。
    结果
  2. 配置XML文件(application.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"
	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.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!--扫描包中的注解把有@Conponment @Service @Repository 注解的类
		为其创建对象并放入Spring容器中-->
	<context:component-scan base-package="com.jd.calculater"></context:component-scan>
	<!--开启自动代理,扫描响应的注解,并产生代理对象。在执行过程中详细讲解
		proxy-target-class属性的值false为默认值使用JDK动态代理
		true则设置为cglib代理
	
	<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
</beans>

注意: 即使proxy-target-class设置为false,如果目标类没有声明接口,则Spring将自动使用CGLib生成代理对象

  1. 编写CalculatorAspect类
@Aspect
@Component
public class CalculatorAspect {
	//前置增强,括号内为切入点表达式:用于指定执行哪些类中的哪些方法时触发增强方法
	@Before("execution(public int mul(int,int))")
	public void before(JoinPoint joinPoint) {
		System.out.println("前置增强");
		//获取目标类对象
		Object target = joinPoint.getTarget();
		//获取目标类需要被增强的方法
		Object[] args = joinPoint.getArgs();
		//获取被增强的方法名
		String name = joinPoint.getSignature().getName();
		System.out.println(target.getClass().getName() + ":The " + name + " method begins.");
		System.out.println(target.getClass().getName() + ":Parameters of the " + name + " method: [" + args[0] + ","
				+ args[1] + "]");
	}
}
  1. 测试类
public class Test {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
		ICalculatorService calculatorService = context.getBean(ICalculatorService.class);
		//把代理对象打印出来
		System.out.println(calculatorService.getClass());
		int result = calculatorService.mul(1, 1);
		System.out.println("结果为:" + result);
	}
}

结果

class com.sun.proxy.$Proxy8
前置增强
com.jd.calculater.CalculatorService:The mul method begins.
com.jd.calculater.CalculatorService:Parameters of the mul method: [1,1]
结果为:1
  • 如果把XML配置文件中的proxy-target-class设置为true或者目标类没有声名接口则会使用cglib代理
    如果打印出的动态代理对象也可以看出使用了cglib代理
class com.jd.calculater.CalculatorService$$EnhancerBySpringCGLIB$$e0cef19
前置增强
com.jd.calculater.CalculatorService:The mul method begins.
com.jd.calculater.CalculatorService:Parameters of the mul method: [1,1]
结果为:1

执行过程

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

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

  3. 扫描带有@Aspect的类中的所有方法

  4. 寻找该类中带有 @Before , @After , @AfterReturning , @Around , @AfterThrowing 注解的方法
    得到该注解
    根据不同的注解判断是对应的是哪一种增强方式

  5. 获取表达式,例如上面的(execution(int mul(int a, int b))这个表达式就是指定需要被增强的方法

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

  7. 为该类创建动态对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值