Spring AOP入门案例

一、AOP(Aspect Orient Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程(OOP)的一种补充和完善。实际项目中我们通常将面向对象理解为一个静态过程(例如一个系统有多少个模块,一个模块有哪些对象,对象有哪些属性),面向切面理解为一个动态过程(在对象运行时动态进行功能扩展或控制对象执行)。
二、应用AOP所需要的相关概念
1.切面(aspect):横切面对象,一般用在扩展功能类说明上,借助@aspect声明。
2.切入点(pointcut):理解为if判断,满足条件即切入进行功能扩展,有如下四个种类:
(1)bean(bean的ID,spring容器管理的ID默认为类名首字母小写)------按对象匹配(粗粒度)
(2)within(包名.类名)------按类匹配(粗粒度)
(3)execution(返回值类型 包名.类名.方法名(参数列表))------按方法匹配(细粒度)
(4)@annotation(注解的类全名)------按注解匹配(细粒度)
其中execution有一种万能用法:execution(* 包名….(…))
3.通知(advice):spring中定义了五种通知类型,分别是:
(1)前置通知(@Before)
(2)后置通知 (@After)
(3)返回通知 (@AfterReturning)
(4)异常通知 (@AfterThrowing)
(5)环绕通知(@around)
4.连接点(joinpoint):一般指被拦截到的方法,当通知为环绕通知时,使用ProceedingJoinPoint
三、入门案例
首先我们在service层写入三个普通方法

package com.cy.pj.sys.service.impl;

import org.springframework.stereotype.Service;

import com.cy.pj.common.annotation.TestAnnotation;

@Service

public class TestService {
	@TestAnnotation //此注解为自定义注解,采用@annotation方式进行功能扩展
	public void method1() {
		System.out.println("method1");
	}
	public void method2() {
		System.out.println("method2");
	}
	public void method3() {
		System.out.println("method3");
	}
}

接下来我们进行功能业务扩展,在service层中的方法前后加入执行时间,以日志方式输出方法执行耗时时间。

package com.cy.pj.common.aspect;

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

import lombok.extern.slf4j.Slf4j;

@Aspect
@Component
@Slf4j
public class TestAOP {
	//@Pointcut("bean(testService)")
	//@Pointcut("within(com.cy.pj.sys.service.impl.TestService)")
	//@Pointcut("execution(* com.cy.pj.sys.service.impl..*.*(..))")
	@Pointcut("@annotation(com.cy.pj.common.annotation.TestAnnotation)")
	public void doPointcut() {}
	@Around("doPointcut()")//环绕通知使用ProceedingJoinPoint
	public Object testObject(ProceedingJoinPoint pjp) throws Throwable {
		long start = System.currentTimeMillis();
		log.info("start:"+start);
		Object result;
		try {
			result = pjp.proceed();//执行被切入的原始方法
			long end = System.currentTimeMillis();
			log.info("end:"+end);
			System.out.println("耗时:"+(end-start));
			return result;
		} catch (Throwable e) {
			e.printStackTrace();
			throw e;
		}

	}
}

采用注解的方式我们首先需要自定义注解,代码如下:

package com.cy.pj.common.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
	//...
}

最终我们进行业务切面测试实现

package com.cy.pj.common.aspect;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


import com.cy.pj.sys.service.impl.TestService;
@SpringBootTest
public class TestSpringAop{
	@Autowired
	private TestService ts;
	@Test
	public void test() {
		ts.method1();
		ts.method2();
		ts.method3();
	}                    
}

测试运行结果如下,运行结果为采用@annotation注解方式进行AOP业务扩展所得结果,method1方法执行扩展功能,如图所示。
在这里插入图片描述

你可能感兴趣的:(java,spring)