详述SpringAOP实现及执行过程

一、代码

1.添加jar类库
在这里插入图片描述
2.按下图结构创建
在这里插入图片描述
3.配置上图代码

①CalculatorService类

package com.jd.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;
	}
}

②ICalculatorService 接口

package com.jd.calculator;

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

③CalculatorAspect类

package com.jd.calculator;

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

@Aspect
@Component/*将CalculatorAspect类创建对象并保存到Spring容器*/
public class CalculatorAspect {
	
	//前置增强:在目标方法执行之前执行
	@Before("execution(int mul(int, int))")
	public void before(JoinPoint jp) {
		Object target = jp.getTarget();
		Object [] args = jp.getArgs();
		String name = jp.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]+"]");
	}
	//后置增强:在目标方法执行后执行,无论目标方法运行期间是否出现异常。注意:后置增强无法获取目标方法执行结果,可以在返回增强中获取
	@After("execution(int mul(int, int))")
	public void after(JoinPoint jp) {
		Object target = jp.getTarget();
		String name = jp.getSignature().getName();
		System.out.println(target.getClass().getName()+":The "+name+" method ends.");
	}
}

④配置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-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>

	<!-- proxy-target-class="false"(默认值为false)创建的是JDK的动态代理,如果是true则创建的是CGLib的动态代理 -->
	<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
	
</beans>

⑤Test 测试类

package com.jd.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.calculator.ICalculatorService;

public class Test {

	public static void main(String[] args) {
		//创建IOC容器并创建对象
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
		//从IOC容器获取对象,由于已经为CalculatorService对象创建了代理对象,所以此时获取的对象为代理对象
		//getBean(ICalculatorService.class)指通过ICalculatorService.class创建动态代理对象,所以ICalculatorService类需要是calculatorService动态代理对象的父类
		ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
		System.out.println(calculatorService.getClass().getName());
		int result = calculatorService.mul(1, 1);
		System.out.println("-->"+result);
	}
}

二、代码分析

1.执行过程

①先执行Test测试类中的main方法
②创建IOC容器

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");

③跳转到application.xml文件中,通过扫描所有以com.jd开头的包为所有含有特定注解的类创建对象

<context:component-scan base-package="com.jd"></context:component-scan>

④Spring寻找有@Aspect注解的类——>寻找该类中方法——>获取方法注解 ——> 获取表达式(execution(int mul(int a, int b))——>检查Spring能扫描到的所有类,将与表达式匹配的方法对应的类——>为该类创建动态对象

<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>

⑤创建JDK的动态代理对象,这里是多态

ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);

⑥通过反射获得动态代理对象的名字

System.out.println(calculatorService.getClass().getName());

⑦先执行CalculatorAspect类中带有@Before注解的前置增强,再通过动态代理对象调用目标方法,最后执行CalculatorAspect类中带有@After注解的后置增强,将返回的值赋给result

int result = calculatorService.mul(1, 1);

⑧最后输出result的值

System.out.println("-->"+result);

2.如何使用JDK创建动态对象

把application.xml中aop:aspectj-autoproxy标签内的proxy-target-class属性设置为false

Test类中代码如下:

//如果创建的是JDK的动态代理,CalculatorService和动态类同级,没有继承关系会出错;
//而动态类是ICalculatorService的接口实现类,存在继承关系
ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);

执行结果如下
在这里插入图片描述

2.如何使用CGLib创建动态对象

把application.xml中aop:aspectj-autoproxy标签内的proxy-target-class属性设置为true
//如果创建的是CGLib的动态代理,CalculatorService是动态类的父类,存在继承关系
ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
或
ICalculatorService calculatorService = applicationContext.getBean(CalculatorService.class);

执行结果如下
在这里插入图片描述

3.为什么没有引asm和CGLib的jar包,还可以用

因为Spring的jar包已经把他们融入了,见下图
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值