如何实现SpingAOP?及其实现过程分析

本文详细介绍了如何实现Spring AOP,包括创建Java工程,导入必要的jar包,配置Spring XML,创建切面类以及执行过程分析。通过实例代码展示了CalculatorService、CalculatorAspect和Test类的使用。同时,讨论了默认的JDK动态代理和如何切换到CGlib代理,以及两者之间的区别和注意事项。
摘要由CSDN通过智能技术生成

                                      实现SpingAOP及其实现过程分析


文章目录

        一、实现SpingAOP

        二、执行过程分析


一、实现SpingAOP

1、创建Java工程

2、创建lib文件夹,导入所需jar包

3、配置Sping配置文件,如下所示:

<?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>

4、创建项目模块,其中自定义一个@Aspect修饰的切面类——>将其创建的对象保存于Spring IOC容器——>自定义增强方法,增强方法也称为通知方法

如图所示


ICalculatorService代码

package com.jd.calculator;

public interface ICalculatorService {

	int mul(int a, int b);

	int div(int a, int b);

}

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) {
		System.out.println(this.getClass().getName()+":The div method begins.");
		System.out.println(this.getClass().getName()+":Parameters of the div method: ["+a+","+b+"]");
		int result = a/b;
		System.out.println(this.getClass().getName()+":Result of the div method:"+result);
		System.out.println(this.getClass().getName()+":The div method ends.");
		return result;
	}
}

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;


@Component
@Aspect("")
public class CalculatorAspect {
	
	@Before("execution( int mul(..))") //前置增强:在目标方法执行之前执行,切入点表达式:用于指定执行哪些类中的哪些方法时触发增强方法
	public void before(JoinPoint jp) {
		Object object = jp.getTarget(); //获取目标对象
		Object [] args =jp.getArgs();  //获取目标方法参数
		String name = jp.getSignature().getName(); //获取目标方法名
		System.out.println(object.getClass().getName()+":The "+name+" method begins.");
		System.out.println(object.getClass().getName()+":Parameters of the "+name+" method: ["+ args[0]+","+args[1]+"]");
	}
	
	@After("execution( int mul(..))") //后置增强:在目标方法执行之后执行不能得到方法的结果
	public void after(JoinPoint jp) {
		Object object = jp.getTarget();
		Object [] args =jp.getArgs();
		String name = jp.getSignature().getName();
		System.out.println(this.getClass().getName()+":The "+name+" method ends.");
	}
}

Test代码

package com.jd.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.calculator.CalculatorService;
import com.jd.calculator.ICalculatorService;

public class Test {
		public static void main(String[] args) {
			ClassPathXmlApplicationContext application= new ClassPathXmlApplicationContext("application.xml");
			ICalculatorService calculatorService = application.getBean(ICalculatorService.class);
			int result = calculatorService.mul(1, 1);
			System.out.println("-->"+result);
		}
}

 


二、执行过程分析

Test类main方法中的第一行:执行流到达配置文建中,会创建IoC容器,并执行一下说明的操作

<context:component-scan base-package="com.jd"></context:component-scan> 
<!--扫描加了Service,Component,Repository注解的类,为其创建对象-->
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy> 
<!--
    Spring寻找@Aspect类(到达CalculatorAspect中)
    ——>寻找该类中方法(该类中方法为mul方法)
    ——>获取方法注解 ——> 获取表达式(execution(int mul(int, int)))
    ——>检查Spring能扫描到的所有类,将与表达式匹配的方法对应的类——>为该类创建动态对象
-->

Test类main方法中的第二行:获取所创建的动态代理对象

Test类main方法中的第三行:执行步骤参照另一篇文章,动态代理的过程,可参考所写的另一篇文章,这里就不过多的赘述

                                               文章链接:https://blog.csdn.net/weixin_42867975/article/details/95983439
Test类main方法中的第四行:输出结果,如下图所示


特变说明:

        ① 默认情况下Sping是JDK动态代理,即在配置文件中,proxy-target-class="false",如果要改为CGlib动态处理,只需要

             proxy-target-class="true"

        ② 该行代码说明

ICalculatorService calculatorService = application.getBean(CalculatorService.class);

          a、如果是JDK动态代理,以上代码就是错误的,运行会出现报如下错误

               这是因为所生成的动态代理对象的代理类与目标类之间没有继承关系,他们都是实现ICalculatorService接口,是同级关系,因                   此代码应改为

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

        b、 如果是CGLib动态代理,以上两种情况都是正确的,此时创建代理对象的代理类继承创建目标对象的类,且目标类实现了                            ICalculatorService接口,因此在以上两种情况都可以

      ③ Sping实现CGLib动态代理时,不需要实现CGLib动态代理所需jar包,这是应为从Spring 3.2开始spring-core-xxx.jar包已集成CGLib和ASM 相关jar包,如下图所示

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值