Spring AOP

目录

AOP定义

Aspectj注解AOP实现与分析

SpringAOP执行过程

SpringAOP执行结果


代码可以通过代理模式进行优化,相关知识点在上篇博客中讲过,故在此不再赘述,这里讲解如何通过Spring AOP技术提高代码的重用性。


AOP定义

AOP(Aspect Oriented Programming 面向切面编程)是一种通过运行期动态代理实现代码复用的机制,是对传统OOP(Object Oriented Programming,面向对象编程 )的补充。目前,Aspectj是Java社区里最完整最流行的AOP框架,在Spring 2.0以上版本中可以通过Aspectj注解或基于XML配置AOP。

Aspectj注解AOP实现与分析

实现类:

@Service
public class CalculatorService implements ICalculatorService{
	@Override
	public int mul(int a, int b) {
		int result = a*b;
		return result;
	}
}

1、添加jar类库

2.application.xml文件中配置:

<context:component-scan base-package="com.jd"></context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
  • ascept配置<aop:aspectj-autoproxy/>为匹配的方法所在的类自动生成动态代理对象,例如:表达式为execution(int mul( . . ))时,匹配到CalculatorService类中的public int mul(int a, int b){...}方法,则为CalculatorService类生成动态代理对象。
  • 匹配过程:Spring寻找有@Aspect注解的类(CalculatorAspect)——>寻找该类中方法——>获取方法的注解 ——>获取表达式(execution(int mul( . . )))——>检查Spring能扫描到的所有类,找到与表达式匹配的方法对应的类 ——>为该类创建动态对象

3、自定义一个@Aspect修饰的切面类——>将其创建的对象保存于Spring IOC容器——>自定义增强方法,增强方法也称为通知方法,指标注有@Before、@AfterRunning、@AfterThrowing、@After或@Around注解的Java方法,下面根据@Before、@After进行分析:

切面的代码:

@Aspect//切面
@Component//将CalculatorAspect类创建对象并保存到Spring容器中
public class CalculatorAspect {
	@Before("execution(int mul(int ,int ))")
	public void before(JoinPoint jp) {
		Object obj=jp.getTarget();
		Object [] args=jp.getArgs();
		String name=jp.getSignature().getName();
		System.out.println(obj.getClass().getName()+":The "+name+" method begins.");
		System.out.println(obj.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
	}
	@After("execution(int mul(..))")
	public void after(JoinPoint jp) {
		Object obj=jp.getTarget();
		String name=jp.getSignature().getName();
		System.out.println(obj.getClass().getName()+":The "+name+" method ends.");
	}
}

分析:

  • @Before表示前置增强(又称前置通知):在目标方法执行之前执行,括号中为切入点表达式:用于指定执行哪些类中的哪些方法时触发增强方法
  • 切入点表达式语法:execution([修饰符] 返回值类型 [包名.类名/接口名.]方法名([参数])[异常]),

说明:a、该表达式用于指定匹配的方法;

           b、修饰符包括访问权限和static、final以及synchronized;

           c、红色中括号框起的部分可以省略;

           d、参数应只写参数类型,省略参数名,如:execution(int mul(int ,int )),

                 或execution(int mul( . . ))用于匹配任何参数的方法

  • joinPoint.getTarget():获取目标类的对象
  • jp.getArgs():获取匹配方法的参数
  • joinPoint.getSignature().getName():获取匹配方法的方法名
  • @After表示后置增强(又称后置通知):在目标方法执行后执行,无论目标方法运行期间是否出现异常。

       注意:后置增强无法获取目标方法执行结果,可以在返回增强中获取

4、编写测试代码,代码如下:

public class Test {
	public static void main(String[] args) {
		//生成使用JDK创建动态代理对象的class文件。注意:该行代码必须放在代理对象产生之前
		System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");		
		ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("application.xml");
		ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
		int result = calculatorService.mul(1, 1);
		System.out.println("-->"+result);
	}
}

分析:

  •  new ClassPathXmlApplicationContext("application.xml"):创建IOC容器,由于CalculatorService类中方法与CalculatorAspect切面类中切入点表达式匹配,所以默认情况下IOC自动为CalculatorService类创建代理类并创建相应的代理对象。
  •  applicationContext.getBean(ICalculatorService.class):从IOC容器获取对象,由于已经为CalculatorService对象创建了代理对象,所以此时获取的对象为代理对象。

注意:当aop:aspectj-autoproxy标签内的proxy-target-class标签属为"false"时, 

           applicationContext.getBean(ICalculatorService.class)不能写成

          applicationContext.getBean(CalculatorService.class)

具体原因如下:

当proxy-target-class标签属性为"false"表示使用JDK生成代理对象,此时创建代理对象的代理类与创建目标对象的类之间没有继承关系,所以不能写成applicationContext.getBean(CalculatorService.class),但是由于此时创建代理对象的代理类实现了ICalculatorService接口,所以可以写成applicationContext.getBean(ICalculatorService.class);

当proxy-target-class标签属性为"true"表示使用CGLib生成代理对象,此时创建代理对象的代理类继承创建目标对象的类,所以可以写作applicationContext.getBean(CalculatorService.class)。

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

  • int result = calculatorService.mul(1, 1):调用代理对象中的mul方法即CalculatorService类中的mul方法,该方法执行过程为:①、执行前置增强;②、执行目标对象的mul方法;③、执行后置增强;

SpringAOP执行过程

  1. Test类中的main函数入口,执行代码new ClassPathXmlApplicationContext("application.xml")创建IOC容器
  2. 转到xml文件中,ascept配置寻找与表达式匹配的方法对应的类(CalculatorService),具体匹配过程如上所述,并为该类创建动态对象
  3. 执行applicationContext.getBean(ICalculatorService.class)从IOC容器获取对象,由于②中自动为CalculatorService类创建了动态对象,所以此时获取的对象为代理对象。
  4. 执行代码int result = calculatorService.mul(1, 1)调用代理对象中的mul方法,该方法执行过程为:①、执行前置增强(CalculatorAspect 类的befor方法);②、执行目标对象的mul方法(CalculatorService类中的mul方法);③、执行后置增强(CalculatorAspect 类的after方法);

SpringAOP执行结果

//前置增强
com.jd.calculator.CalculatorService:The mul method begins.
com.jd.calculator.CalculatorService:Parameters of the mul method: [1,1]
//后置增强
com.jd.calculator.CalculatorService:The mul method ends.
-->1

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值