详述SpringAOP

目录

 

一、AOP是什么

二、为什么要用AOP

三、AOP中的几种方法注释

(1)@Before

(2)@After

(3)@AfterReturning 

(4)@AfterThrowing 

(5)@Around


一、AOP是什么

Aspect Oriented Programming(AOP)是较为热门的一个话题。AOP,国内大致译作“面向切面编程”。

“面向切面编程”,这样的名字并不是非常容易理解,且容易产生一些误导。有些人认为“OOP/OOD11即将落伍,AOP是新一代软件开发方式”。显然,发言者并没有理解AOP的含义。Aspect,的确是“方面”的意思。不过,汉语传统语义中的“方面”,大多数情况下指的是一件事情的不同维度、或者说不同角度上的特性,比如我们常说:“这件事情要从几个方面来看待”,往往意思是:需要从不同的角度来看待同一个事物。这里的“方面”,指的是事物的外在特性在不同观察角度下的体现。而在AOP中,Aspect的含义,可能更多的理解为“切面”比较合适。

可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,AOP可以说也是这种目标的一种实现。

在Spring中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

二、为什么要用AOP

利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

三、AOP中的几种方法注释

现在编写程序实现如下功能,计算两个数的商,且有以下输出:

要求详细输出调用方法的信息及传入参数还有执行阶段信息。 假设我们直接将字符写入方法内,像这样:

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;
	}

则当我们再定义多个方法时,代码重复太多,于是我们定义另外一个方法:

private void advice(String method,int a,int b) {
		System.out.println(this.getClass().getName()+":The "+method+" begins.");
	    System.out.println(this.getClass().getName()+":Parameters of the "+method+":["+a+","+b+"]");
	}

但这样依然不够让我们的代码得到简化,于是就要用到AOP。

首先定义SpringConfig文件:

<?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:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
	
	<context:component-scan base-package="com.jd"></context:component-scan>
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

定义ComputerService类:

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;
	}
	
}

定义ComputerAOP类(先不添加内容):


import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ComputerAOP {
	
	
}

定义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);
		System.out.println(computerService.getClass().getName());
		System.out.println(computerService.div(1, 1));
		applicationContext.close();
	}
}

当我们在执行某个方法时大概有三个阶段:开始,结束,返回结果,接下来就介绍AOP中的几个方法注释

(1)@Before

Before即为前置方法,即在调用目标方法前执行的方法。定义如下:

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

@Aspect
@Component
public class ComputerAOP {
	
	@Before("execution(public int com.jd.computer.service.ComputerService.*(..))")
	public void before(JoinPoint jp) {//JoinPoint 连接点对象
		Object [] args = jp.getArgs();//得到方法中传入的参数
		
		Signature signature = jp.getSignature();//得到切入点调用的的目标类的方法
		String name = signature.getName();//得到目标方法的名字
		System.out.println(this.getClass().getName()+":The "+name+" begins.");
	    System.out.println(this.getClass().getName()+":Parameters of the "+name+":["+args[0]+","+args[1]+"]");
	}
}

运行Test类main方法:

(2)@After

After即为后置方法,在执行完目标方法后执行该方法。定义如下:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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
public class ComputerAOP {
	
	@Before("execution(public int com.jd.computer.service.ComputerService.*(..))")//扫描ComputerService类中的方法,与目标方法建立联系
	public void before(JoinPoint jp) {//JoinPoint 连接点对象
		Object [] args = jp.getArgs();//得到方法中传入的参数
		
		Signature signature = jp.getSignature();//得到切入点调用的的目标类的方法
		String name = signature.getName();//得到目标方法的名字
		System.out.println(this.getClass().getName()+":The "+name+" begins.");
	    System.out.println(this.getClass().getName()+":Parameters of the "+name+":["+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+" ends.");
	}
	
}

 运行Test类中的main方法:

(3)@AfterReturning 

AfterReturning 及执行完后置方法后用于返回结果的方法,但与之前不同的是,当有异常时,该方法不执行。定义如下:

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

@Aspect
@Component
public class ComputerAOP {
	
	@Before("execution(public int com.jd.computer.service.ComputerService.*(..))")
	public void before(JoinPoint jp) {//JoinPoint 连接点对象
		Object [] args = jp.getArgs();//得到方法中传入的参数
		
		Signature signature = jp.getSignature();//得到切入点调用的的目标类的方法
		String name = signature.getName();//得到目标方法的名字
		System.out.println(this.getClass().getName()+":The "+name+" begins.");
	    System.out.println(this.getClass().getName()+":Parameters of the "+name+":["+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+" ends.");
	}
	
	@AfterReturning(value = "execution(public int com.jd.computer.service.ComputerService.*(..))",returning = "result")
	public void afterReturning(JoinPoint jp,Object result) {
		System.out.println(this.getClass().getName()+":Result of the div method:"+result);
	}
}

运行Test类中main方法: 

(4)@AfterThrowing 

AfterThrowing 即为用于抛出异常的方法,与上个相反,有异常时才执行,无异常不执行。定义如下:

import org.aspectj.lang.JoinPoint;
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.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ComputerAOP {
	
	@Before("execution(public int com.jd.computer.service.ComputerService.*(..))")
	public void before(JoinPoint jp) {//JoinPoint 连接点对象
		Object [] args = jp.getArgs();//得到方法中传入的参数
		
		Signature signature = jp.getSignature();//得到切入点调用的的目标类的方法
		String name = signature.getName();//得到目标方法的名字
		System.out.println(this.getClass().getName()+":The "+name+" begins.");
	    System.out.println(this.getClass().getName()+":Parameters of the "+name+":["+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+" ends.");
	}
	
	@AfterReturning(value = "execution(public int com.jd.computer.service.ComputerService.*(..))",returning = "result")
	public void afterReturning(JoinPoint jp,Object result) {
		System.out.println(this.getClass().getName()+":Result of the div 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());
	}
}

运行Test类中的main方法:(“0做分母”异常)

(5)@Around

Around可以同时前四个方法的整个过程,即开始,结束,返回结果,若有异常,不返回结果,返回异常。定义如下:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ComputerAOP {
	
	@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+" begins.");
	    System.out.println(this.getClass().getName()+":Parameters of the "+name+":["+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+" ends.");
			}
			System.out.println(this.getClass().getName()+":Result of the div method:"+result);
			return result;
		} catch (Throwable e) {
			System.out.println(e.getMessage());
		}
		return -1;
	}
	
}

运行Test类(有异常时):

 运行Test类(无异常时):

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值