SpringAOP实现及执行过程

文章目录

  • AOP实现
  • 执行过程

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包暂时可以不导入。
    SpringAOP实现及执行过程_第1张图片
  2. 配置XML文件(application.xml文件)

<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">
	
	<context:component-scan base-package="com.jd.calculater">context:component-scan>
	<!--开启自动代理,扫描响应的注解,并产生代理对象。在执行过程中详细讲解
		proxy-target-class属性的值false为默认值使用JDK动态代理
		true则设置为cglib代理
	
	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. 为该类创建动态对象

你可能感兴趣的:(框架,Java,Spring,AOP,动态代理)