Spring学习之AOP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangchengming1/article/details/81283961

什么是AOP

  • AOP利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
  • 通俗来讲,在我们的应用中,诸如常见的日志、安全、异常处理和事物等逻辑都很重要,在不适用AOP的过去,我们需要将共同部分的这段代码写在一个独立的类独立的方法里,然后再去调用。但是有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。

举一个比较形象的例子。在不使用AOP的应用中,一般日志处理都是这个样子的:

这里写图片描述

因为日志处理代码是相同的,为了实现代码复用,我们可能把日志处理抽离成一个新的方法。但是这样我们仍然必须手动插入这些方法。这样子做虽然是符合面向对象思想,但是方法之间是强耦合的,一旦处理日志的方法需要更改,就必须在每个调用日志处理的方法中做修改,这样子显然是不好的。

使用AOP之后可以是这样子的:

这里写图片描述

AOP的思想是:我们可以通过动态代理,可以在指定位置执行对应流程。这样就可以将一些横向的功能抽离出来形成一个独立的模块,然后在指定位置插入这些功能。比如我们可以将test1()作为一个切入点,也就是说在test1()执行前或者执行后,执行recordLog()方法。

AOP的基本概念

描述切面的常用术语,也是我们在开发中经常使用的有通知(advice)、切点(pointcut)、连接点(joinpoint)、切面(Aspect)。

  • 通知(Advice)
    通知定义了切面是什么以及什么时候使用。Spring切面可以应用五种类型的通知:
    前置通知(Before): 在目标方法被调用之前通知功能。
    后置通知(After):在目标方法被调用之后通知功能。
    返回通知(After-returning):在目标方法执行成功之后调用通知。
    异常通知(After-throwing):在目标方法抛出异常之后调用通知。
    环绕通知(Around):通知包含了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

  • 连接点(Join Point):在应用中执行过程中能够插入切面的一个点。

  • 切点(Pointcut):切点定义了匹配通知在何处织入。

  • 切面(Aspect):切面是通知和切点的集合。通知和切点共同定义了切面的全部内容–它是什么、在何时在何处完成功能

Spring对AOP的支持

Spring提供了四种类型的AOP支持

  • 基于纯代理的经典Spring AOP
  • 纯POJO切面
  • @AspectJ注解驱动的切面
  • 注入式AspectJ切面(适用于Spring各个版本)

AOP切点表达式

AspectJ指示器 描述
arg() 限制连接点匹配参数由指定类型的执行方法
@arg() 限制连接点匹配参数由指定注解标注的执行方法
execution() 用于匹配是连接点的执行方法
this() 限制连接点匹配AOP代理的bean引用为指定类型的类
target 限制连接点匹配目标对象为指定类型的类
@target() 限制连接点匹配特定的执行对象
within() 限制连接点匹配指定的类型
@within() 限制连接点匹配指定注解所标注的类型
@annotation 限制连接点匹配有指定注解的连接点

AOP使用场景

AOP用来封装横切关注点,具体可以在下面的场景中使用:

  • Authentication 权限
  • Caching 缓存
  • Context passing 内容传递
  • Error handling 错误处理
  • Lazy loading 懒加载
  • Debugging  调试
  • logging, tracing, profiling and monitoring 记录跟踪 优化 校准
  • Performance optimization 性能优化
  • Persistence  持久化
  • Resource pooling 资源池
  • Synchronization 同步
  • Transactions 事务

AOP功能简单实现

  • 创建接口
package com.example.aop;

public interface Person {

	public void say();
}

  • 创建实现类
package com.example.aop;

public class Student implements Person{

	@Override
	public void say() {
		System.out.println("I'm a student");
	}
}

  • 创建切面类
package com.example.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class AspectPerson {

	@Pointcut("execution(* *.say(..))")
	public void say() {}
	
	@Before("say()")
	public void before() {
		System.out.println("before");
	}
	
	@After("say()")
	public void after() {
		System.out.println("after");
	}
	
	@Around("say()")
	public Object around(ProceedingJoinPoint pj) {
		System.out.println("around before");
		Object o = null;
		try {
			o = pj.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("around after");
		return o;
	}
	
}

  • 创建xml(当然你也可以使用javaConfig的方法,主要使用EnableAspectJAutoProxy注解)
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
 
 	<!-- 开启aop -->
	<aop:aspectj-autoproxy/>
    <bean id="student" class="com.example.aop.Student"/>
	<bean class="com.example.aop.AspectPerson"/>
</beans>
  • 创建测试类
package com.example.aop;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class aopTest {

	@Test
	public void test() {
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("aopBean.xml");
		Person bean2 = (Person)ac.getBean("student");
		bean2.say();
	}

}

使用AOP的好处

猜你喜欢

转载自blog.csdn.net/wangchengming1/article/details/81283961