详述Spring AOP

什么是AOP?

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

为什么用AOP?

通过Spring AOP技术可以提高代码的重用性。

怎么使用AOP?

1、添加相应的jar类库。
在这里插入图片描述
2、Spring配置文件添加<aop:aspectj-autoproxy></aop:aspectj-autoproxy>,该配置作用:如果创建目标对象的目标类中的方法与AspectJ切面中切入点表达式匹配,则自动为该目标对象生成动态代理对象。

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

例子如下:
①实行运算方法的类ComputerService.java:

package com.jd.computer.service;

import org.springframework.stereotype.Service;

@Service
public class ComputerService {

	public int add(int a, int b) {
		System.out.println(this.getClass().getName()+":The add method begins.");
		System.out.println(this.getClass().getName()+":Parameters of the add method: ["+a+","+b+"]");
		return a+b;
	}

	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+"]");
		return a/b;
	}
}

4、可以看出此时有很多重复的代码,可以用AOP进行简化,由@Aspect修饰的切面类如下:

package com.jd.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect//将该类声明为切面类
@Component//将该类对象放入IOC容器
public class ComputerAOP {

	//前置增强(又称前置通知):在目标方法执行之前执行
	@Before("execution(public int com.jd.computer.service.ComputerService.*(..))")
	public void before(JoinPoint jp) {
		Object [] args = jp.getArgs();
		Signature signature =jp.getSignature();
		String name = signature.getName();
		System.out.println(this.getClass().getName()+":The "+name+" method begins.");
	    System.out.println(this.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
	}
	
	//后置增强(又称后置通知):在目标方法执行后执行,无论目标方法运行期间是否出现异常。注意:后置增强无法获取目标方法执行结果,可在返回增强中获取。
	@After("execution(public int com.jd.computer.service.ComputerService.*(..))")
	public void after(JoinPoint jp) {
		Signature signature =jp.getSignature();
		String name = signature.getName();
		System.out.println(this.getClass().getName()+":The "+name+" method ends.");
	}
	
	//返回增强(又称返回通知):在目标方法正常结束后执行,可以获取目标方法的执行结果,如果出现异常,则不执行。
	@AfterReturning(value = "execution(public int com.jd.computer.service.ComputerService.*(..))",returning = "result")
	public void afterReturning(JoinPoint jp, Object result) {
		Signature signature =jp.getSignature();
		String name = signature.getName();
		System.out.println(this.getClass().getName()+":Result of the "+name+" method:"+result);
	}
	
	//异常增强(又称异常通知):目标方法抛出异常之后执行,可以访问到异常对象,且可以指定在出现哪种异常时才执行增强代码。
	@AfterThrowing(value = "execution(public int com.jd.computer.service.ComputerService.*(..))",throwing = "e")
	public void afterThrowing(JoinPoint jp, Exception e) {
		System.out.println(e.getMessage());
	}

	//环绕增强:目标方法执行前后都可以织入增强处理,@Around修饰的方法中可以实现@Before,@After,@AfterReturning和@AfterThrowing增强效果,可以实现动态代理全过程。
	/*@Around(value = "execution(public int com.jd.computer.service.ComputerService.*(..))")
	public Object around(ProceedingJoinPoint pjp) {
		Object [] args = pjp.getArgs();
		Signature signature = pjp.getSignature();
		String name = signature.getName();
		System.out.println(this.getClass().getName()+":The "+name+" method begins.");
		System.out.println(this.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]")

		try {
			Object result = null;
			try {
				Object object = pjp.getTarget();//目标类创建的对象
				System.out.println(object.getClass().getName());
				result = pjp.proceed();
			} finally {
				System.out.println(this.getClass().getName()+":The "+name+" method ends.");
			}
			System.out.println(this.getClass().getName()+":Result of the "+name+" method:"+result);
			return result;
		} catch (Throwable e) {
			System.out.println(e.getMessage());
		}
		return -1;
	}*/
}

添加切面类后的ComputerService.java可以进行简化:

package com.jd.computer.service;

import org.springframework.stereotype.Service;

@Service
public class ComputerService implements IComputerService {

	public int add(int a, int b) {
		int result = a+b;
		return result;
	}

	public int div(int a, int b) {
		int result = a/b;
		return result;
	}
}

5、此时编写测试代码,代码如下:

package com.jd.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jd.computer.service.IComputerService;

public class Test {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
		IComputerService computerService = applicationContext.getBean(IComputerService.class);
		int result = computerService.div(1, 1);
		System.out.println(result);
		applicationContext.close();
	}
}

因为此时没有异常,则@Before、@AfterRunning、@AfterThrowing、@After修饰的java方法都执行了,输出结果为:
在这里插入图片描述
若改成int result = computerService.div(1, 0);,则不会执行@AfterReturning修饰的java方法:
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值