Spring AOP

天大地大妈咪最大 提交于 2020-03-08 10:36:49

AOP

AOP(Aspect Oriented Programming 面向切面编程)是一种通过运行期动态代理实现代码复用的机制,是对传统OOP(Object Oriented Programming,面向对象编程 )的补充。

AOP的作用

在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加。AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),切面将那些与业务无关,却被业务模块共同调用的逻辑提取并封装起来,减少了系统中的重复代码降低了模块间的耦合度同时提高了系统的可维护性

实现AOP

1、添加jar类库
在这里插入图片描述
2、Spring配置文件添加< aop:aspectj-autoproxy/>,该配置作用:如果创建目标对象的目标类中的方法与AspectJ切面中切入点表达式匹配,则自动为该目标对象生成动态代理对象,
在这里插入图片描述
3、自定义一个@Aspect修饰的切面类——>将其创建的对象保存于Spring IOC容器——>自定义增强方法,增强方法也称为通知方法,指有@Before、@AfterRunning、@AfterThrowing、@After或@Around注解修饰的Java方法。
代码如下:

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
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 add 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());
	}
	
	//环绕增强:目标方法执行前后都可以织入增强处理
	/*注意:
	1、@Before、@After、@AfterRunning和@AfterThrowing修饰的方法可以通过声明JoinPoint 类型参数变量获取目标方法的信息(方法名、参数列表等信息);@Around修饰的方法必须声明ProceedingJoinPoint类型的参数,该变量可以决定是否执行目标方法;
	2、@Before、@After、@AfterRunning和@AfterThrowing修饰的方法没有返回值;而@Around修饰的方法必须有返回值,返回值为目标方法的返回值;*/
	@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 add 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;
	}

}

application配置文件:

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

	<context:component-scan base-package="com.jd"></context:component-scan>
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
	<!-- Spring配置文件添加<aop:aspectj-autoproxy/>
	该配置作用:如果创建目标对象的目标类中的方法与AspectJ切面中切入点表达式匹配,则自动为该目标对象生成动态代理对象, -->

</beans>

测试类:

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);
		System.out.println(computerService.getClass().getName());
		int result = computerService.add(1,2);
		System.out.println(result);
		applicationContext.close();
	}

}

服务层代码:

package com.jd.computer.service;

/*
 * 服务层接口
 */
public interface IComputerService {
	
	int add(int a, int b);
	int div(int a, int b);

}

package com.jd.computer.service;

import org.springframework.stereotype.Service;
/*
 * 服务层接口实现类
 */
@Service
public class ComputerService implements IComputerService {

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

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

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!